Java Collectors.toSet()是否总是返回哈希集?合同是什么?

Java Collectors.toSet()是否总是返回哈希集?合同是什么?,java,java-8,collectors,Java,Java 8,Collectors,Javadoc说 返回一个收集器,该收集器将输入元素累加到新的 设置对于类型、可变性、可序列化性、, 或返回集合的线程安全性;如果更多地控制 返回的集合是必需的,请使用 toCollection(java.util.function.Supplier) 因此Collectors.toCollection(HashSet::new)在这里避免问题似乎是个好主意() 我的问题是,尽管我尽了最大努力,但除了从HashSet 以下是我使用的代码: public static void main(Stri

Javadoc说

返回一个收集器,该收集器将输入元素累加到新的 设置对于类型、可变性、可序列化性、, 或返回集合的线程安全性;如果更多地控制 返回的集合是必需的,请使用 toCollection(java.util.function.Supplier)

因此
Collectors.toCollection(HashSet::new)
在这里避免问题似乎是个好主意()

我的问题是,尽管我尽了最大努力,但除了从
HashSet

以下是我使用的代码:

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");
        }
    }
}
publicstaticvoidmain(字符串[]args){
listl=Arrays.asList(1,2,3);

对于(int i=0;i++,JavaDoc声明没有保证,但这并不阻止任何特定的实现总是返回特定类型的集合。这只是设计者说他们不想限制未来实现的功能。它没有说明当前实现的实际功能


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

收集器::toSet
返回的
集合的类型是一个实现细节。您不应该依靠实现细节在将来的版本中保持不变。现在,他们使用的是,但将来他们可能希望使用不同类型的集合

当前OpenJDK的实现(以及AFAIK和Oracle的实现)确实总是返回一个
哈希集
——但是没有保证。如果您以某种方式假设
收集器.toSet()
将返回一个
哈希集,JDK的未来版本可能会很好地改变这种行为并破坏您的代码(例如,明确地放下它)。

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

例如,未来的java版本可能返回专门的不可变集实现,与当前的
HashSet
实现相比,该实现的读取效率更高,占用的内存更少,它实际上只是
HashMap
的包装器。最终可能会导致这样的优化

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


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

HashSet::new
目前被硬编码为返回的
集的供应商(它解释了您的结果)。但不能保证这在未来的版本中不会改变。他们为什么要保证?如果他们认为其他东西更好,不定义行为会让他们自由地改变它。@SashaSalauyou问题不是代码方面的,而是Javadoc方面的。我的问题更多的是“他们为什么要写它?”.但正如我所说的,这是我对英语的理解造成的。@YassinHajaj旁注:
I++JavaDoc主要是关于规范的;它说明了类或方法必须做什么,以及用户可以依赖什么。一个清晰的规范——与实现分离——通过告诉读者他们可以依赖什么,让读者受益匪浅d维护人员,告诉他们已经向用户做出了什么承诺(因此,他们有多大的灵活性来改进或重新创建实现)几乎从定义上讲,任何给定的实现都会更加具体,这就是为什么我们要编写单独的规范——这样您就不会依赖于实现的偶然特性。谢谢Jim。这确实是我没有想到的一个角度。我想这要归咎于我对英语的理解。