java – Map:为Integer和Double定义一个方法,但不是String

我正在尝试为我的新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;
    }

} 

请随意禁止其他数字的子类型,即通过抛出异常,如您所见.

点赞