【问题标题】:Do Collections functional methods call get, put, etc?Collections 函数方法是否调用 get、put 等?
【发布时间】:2017-05-27 14:50:17
【问题描述】:

我已经使用 Java 1.6(维护遗留工具)多年,并且刚刚开始迁移到 1.8。一大变化是 java.util.Collections 套件中的函数式方法。对我来说最大的担忧是我有几个集合扩展,它们在修改时应用了仔细的检查或算法。默认方法是否调用已定义的 put(..)、get(...)、remove(..) 等函数,还是我必须进行重大返工才能使其工作?

例如(忽略空检查等只包含值

public class LimitedMap extends HashMap<String, Integer>{
    @Override
    public Integer put(String key, Integer value){
        if(value> 10) throw new IllegalArgumentException();
        return super.put(key, value);
    }

    @Override
    public Integer computeIfAbsent(String key, Function<? super String, ? extends Integer> mappingFunction) {
        return super.computeIfAbsent(key, mappingFunction);
    }
}

使用这对函数:我是否仍需要进行详细的覆盖并将新的检查放入 computeIfAbsent 函数?

【问题讨论】:

  • 你不知道,无论如何它都可能改变,这就是为什么你应该支持组合而不是继承:jtechies.blogspot.fr/2012/07/…。如果您使用了组合,那么所有新添加的默认方法都会简单地委托给您自己的方法。
  • 如果你想知道新的默认方法是做什么的,为什么不直接看源码呢? JDK 附带了 Java 运行时库的所有类的源代码,任何好的 IDE 都可以很容易地查看该源代码。您使用的 IDE 不错,对吧?
  • @Radiodef 您错过了重点:OP 的 Map 实现扩展了 HashMap,其中默认方法被覆盖。 HashMap 的 computeIfAbsent() 是否调用 put() 是一个实现细节,OP 不能依赖它。
  • @JBNizet 是的,你是对的。无论如何,我完全同意您对组成和授权的评论。例如,这可以用AbstractMap 轻松完成。
  • 正如@JBNizet 所说,您不应该扩展不打算专门化的实现类。你要重复the failure of others。并不是 Java 8 没有引入这个示例问题,而是 Java 8,更新 20。这说明了实现细节是多么脆弱。另见Inheritance, composition and default methods...

标签: java collections lambda java-8


【解决方案1】:

您可以确定只能使用 Java 8 之前的接口方法的唯一方法是,如果您能以某种方式委托给 接口 中的默认方法实现(在这种情况下为Map&lt;K, V&gt; )。

也就是说,如果你能写出类似下面的东西(你不能)。

public class LimitedMap extends HashMap<String, Integer> {

    @Override
    public Integer computeIfAbsent(String key,
            Function<? super String, ? extends Integer> mappingFunction) {

        return Map.super.computeIfAbsent(key, mappingFunction);
    }
}

不幸的是,这是不合法的,因为您只能调用已覆盖的方法(这里是来自 HashMap&lt;String, Integer&gt; 的方法),但不能调用被继承方法可能已覆盖的方法(这些是 super 的正常规则方法调用)。

因此,对于您的情况,我看到的唯一解决方法是在这样的帮助器类中创建接口默认方法实现的副本:

public class Maps {

    public static <K, V> V computeIfAbsent(Map<K, V> map,
            K key, Function<? super K, ? extends V> mappingFunction) {
        Objects.requireNonNull(mappingFunction);
        V v;
        if ((v = map.get(key)) == null) {
            V newValue;
            if ((newValue = mappingFunction.apply(key)) != null) {
                map.put(key, newValue);
                return newValue;
            }
        }

        return v;
    }
}

这是来自 java.util.Map 的实现,作为一个静态方法,由一个附加参数 map 增强,供实例操作。

有了这样一个帮助类,你现在可以编写了

public class LimitedMap extends HashMap<String, Integer> {

    @Override
    public Integer computeIfAbsent(String key,
            Function<? super String, ? extends Integer> mappingFunction) {

        return Maps.computeIfAbsent(this, key, mappingFunction);
    }
}

这不是最漂亮的解决方案,但应该只需付出有限的努力即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-09
    • 1970-01-01
    • 2011-03-16
    • 2010-10-12
    • 2016-09-23
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    相关资源
    最近更新 更多