我正在尝试为我的新Map类定义一个方法putIfGreaterThan()(给定一个键,只有当新值大于旧值时才用新值替换旧值).
我知道我可以通过合成(通过拥有私有的最终Map< String,Double> map;在新类中然后将Map传递给构造函数)或通过在我的新类中实现Map接口并将Map传递给构造函数(虽然我不确定哪种方法更优越).
我的主要问题是我需要能够在< String,Double>上调用putIfGreaterThan()方法.和< String,Integer>但不是< String,String> (因为在< String,String>)上调用它是没有意义的.如果我使用泛型(< K,V>),客户端可以传递< String,String>这是不允许的.另一方面,如果我允许Double,我将无法传递整数,反之亦然.如何定义允许Integer或Double但不允许String的方法?
注意:我无法定义两个构造函数(一个用于Double,一个用于Integer)因为我得到错误:方法XX的擦除与XX类型中的另一个方法相同.
最佳答案 您可以使用装饰器模式并将泛型限制为Number的子类型,您可以比较而不使用从 this answer获取的小技巧进行比较.它采用数字实例的字符串表示并创建BigDecimal的实例 – 从而绕过铸造任何一种.
下面你会找到装饰器的相关实现细节,当然你需要覆盖Map接口的其余方法.
public class GreaterThanDecorator<K, V extends Number> implements Map<K, V> {
private final Map<K, V> delegate;
public GreaterThanDecorator(Map<K, V> delegate) {
this.delegate = delegate;
}
public V putIfGreaterThan(K key, V value) {
V old = delegate.get(key);
if (old == null) {
delegate.put(key, value);
return null;
}
BigDecimal newValue = new BigDecimal(value.toString());
BigDecimal oldValue = new BigDecimal(old.toString());
if (newValue.compareTo(oldValue) >= 1)
old = delegate.put(key, value);
return old;
}
}
请随意禁止其他数字的子类型,即通过抛出异常,如您所见.