繁体   English   中英

Collectors.toSet() 是否总是返回一个 HashSet ? 合同是什么?

[英]Does Collectors.toSet() always return a HashSet ? What is the contract?

Javadoc 说

返回一个将输入元素累积到新 Set 中的收集器。 返回的 Set 的类型、可变性、可序列化性或线程安全性没有任何保证; 如果需要对返回的 Set 进行更多控制,请使用 toCollection(java.util.function.Supplier)。

所以Collectors.toCollection(HashSet::new)似乎是避免问题的好主意( SO question )。

我的问题是, toSet()我所能,除了HashSet之外,我无法从toSet()返回任何其他内容

这是我使用的代码:

public static void main(String[] args) {
    List<Integer> l = Arrays.asList(1,2,3);

    for (int i = 0 ; i++<1_000_000;){
        Class clazz = l.stream().collect(Collectors.toSet()).getClass();

        if (!clazz.equals(HashSet.class)) {
            System.out.println("Not a HashSet");
        }
    }
}

那么,为什么 Javadoc 声明不能保证,而实际上,有...

JavaDoc表示无法保证 ,但这并不妨碍任何特定实现始终返回特定类型的集合。 这只是设计师说他们不想限制未来的实现可以做什么。 它没有说明当前的实现实际上做了什么。

换句话说,您已经发现了实现定义的行为(总是返回一个HashSet ),但如果依靠它,您将来可能会遇到问题。

当前OpenJDK的实现(以及AFAIK,Oracle也是如此)确实总是返回一个HashSet - 但是不能保证这一点。 如果你以某种方式假设Collectors.toSet()将返回一个HashSet (例如,明确地向下转换它),JDK的未来版本可能会很好地改变这种行为并打破你的代码。

Collectors::toSet返回的Set类型是一个实现细节。 您不应该依赖实现细节在将来的版本中保持不变。 现在,他们使用HashSet ,但将来他们可能想要使用不同类型的集合。

例如,未来的Java版本可能会返回专门的不可变集合实现,这些实现对于读取更有效,并且比当前的HashSet实现消耗更少的内存,而HashSet实际上只是HashMap一个包装器。 瓦尔哈拉项目最终可能会导致这种优化。

他们甚至可能选择基于数据量返回不同的集合类型,例如,如果事先知道将返回零个或一个元素,则为空或单个集合。

因此,通过根据当前实施提供的保证数量少于可能,他们为未来的改进敞开大门。

我想你要找的是: Collectors.toCollection(LinkedHashSet::new)

怎么样

        Set<String> tree =s.stream().collect(Collectors.toCollection(TreeSet::new));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM