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

时间:2016-05-05 16:37:52

标签: java java-8 collectors

Javadoc说

  

返回一个将输入元素累积为新元素的收集器   组。不保证类型,可变性,可串行性,   或者返回Set的线程安全性;如果更多的控制权   返回Set是必需的,使用   toCollection(java.util.function.Supplier)。

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

我的问题是,就像我尝试过的那样艰难,我无法从toSet()返回任何其他内容而不是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");
        }
    }
}

为什么然后,Javadoc说实际上没有保证,有......

6 个答案:

答案 0 :(得分:12)

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

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

答案 1 :(得分:4)

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

答案 2 :(得分:3)

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

答案 3 :(得分:2)

例如,未来的Java版本可能会返回专门的不可变集合实现,这些实现对于读取更有效,并且比当前max = float("-inf") min = float("inf") count_l = 0 count_s = 0 def safecast(cast_type, value, default=None): try: default = cast_type(value) finally: return default def input_until(prompt, cast_type, value, default=None): while True: ret = safecast(cast_type, raw_input(prompt), default=default) if ret != value: yield ret else: break for num in input_until("Enter a number\n:", float, 0): if num != 0: if num < min: min = num count_s = 1 elif num > max: max = num count_l = 1 elif num == min: count_s += 1 elif num == max: count_l += 1 def result(max, min): print('Largest Number Entered:') , max print('Smallest Number Entered:'), min print('Occurance of largest number is: '), count_l print('Occurance of smallest number is: '), count_s result (max, min) 实现消耗更少的内存,这实际上只是HashSet的包装器。 Project valhalla最终可能会导致这种优化。

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

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

答案 4 :(得分:1)

我认为你在寻找的是:  Collectors.toCollection(LinkedHashSet::new)

答案 5 :(得分:-3)

怎么样

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