映射:为类型整数和双精度但不是字符串定义方法 [英] Map: Defining a Method for Type Integer and Double but not String
问题描述
我试图为我的新的 Map
类定义一个方法 putIfGreaterThan()
只有当新值大于旧值时,才会使用新值替换旧值)。
据我所知,我可以通过合成(通过具有私人最终地图< String,Double>地图;
在新类中,然后将 Map
传递给构造函数),或者通过在我的新类中实现 Map
接口并传递一个 Map
给构造函数(尽管我不确定哪种方法更好)。
我的主要问题是我需要能够在< String,Double>
和<$ c上调用方法 putIfGreaterThan()
$ c>< String,Integer> ,但不在< String,String>
上(因为调用它没有意义< String,String>
)。如果我使用泛型(< K,V>
),客户端可以传递一个< String,String>
不允许。另一方面,如果我允许 Double
,我将无法传递整数
,反之亦然。我怎样才能定义一个方法来允许Integer或Double而不是String?
您可以使用装饰器并将泛型限制为 Number
的子类型,您可以使用这个答案。它接受数字实例的字符串表示并创建一个 BigDecimal
的实例 - 从而规避任何类型的转换。
下面你会发现装饰器的相关实现细节,当然你需要重写 Map
接口的其余方法。
public class GreaterThanDecorator< K,V extends Number>实现Map< K,V> {
私人最终地图< K,V>代表;
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);
返回null;
}
BigDecimal newValue = new BigDecimal(value.toString());
BigDecimal oldValue = new BigDecimal(old.toString());
if(newValue.compareTo(oldValue)> = 1)
old = delegate.put(key,value);
返回旧的;
请随时禁止其他子类型的 Number
,即通过抛出一个异常,正如您认为的那样。
I'm attempting to define a method putIfGreaterThan()
for my new Map
class (given a key it replaces the old value with the new value only if the new value is greater than the old value).
I understand I could accomplish this either via composition (by having a private final Map<String, Double> map;
in new class and then passing a Map
to constructor) or by implementing the Map
interface in my new class and passing a Map
to the constructor (although I'm not sure which approach is superior).
My main problem is that I need to be able to call the method putIfGreaterThan()
on <String, Double>
and <String, Integer>
but not on <String, String>
(bec it doesn't make sense to call it on <String, String>
). If I use generics ( <K, V>
) the client can pass a <String, String>
which is not allowed. On the other hand if I allow a Double
I will not be able to pass an Integer
or vice versa. How can I define a method to allow either Integer or Double but not String?
Note: I'm unable to define two constructors (one for Double and one for Integer) bec I get the error: Erasure of method XX is the same as another method in type XX .
解决方案 You can use the decorator pattern and limit the generics to subtypes of Number
, which you can than compare without casting with a little trick taken from this answer. It takes the string representation of the number instances and creates an instance of BigDecimal
- thus circumventing casting of any kind.
Below you find the relevant implementation details of the decorator, of course you'll need to override the remaining methods of the Map
interface.
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;
}
}
Feel free to forbid the other subtypes of Number
, i.e. by throwing an exception, as you see fit.
这篇关于映射:为类型整数和双精度但不是字符串定义方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!