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说实际上没有保证,有......
答案 0 :(得分:12)
JavaDoc声明没有保证,但这并不妨碍任何特定实现始终返回特定类型的集合。这只是设计师说他们不想限制未来的实现可以做什么。它没有说明当前的实现实际上做了什么。
换句话说,您已经发现了实现定义的行为(总是返回HashSet
),但是如果依靠它,您将来可能会遇到问题。
答案 1 :(得分:4)
当前OpenJDK的实现(以及AFAIK,Oracle也是如此)确实总是返回HashSet
- 但是没有保证。如果您以某种方式假设Collectors.toSet()
将返回HashSet
(例如,明确地向下转换它),则JDK的未来版本可能会很好地改变此行为并破坏您的代码。
答案 2 :(得分:3)
Set
返回的Collectors::toSet
类型是一个实现细节。您不应该依赖实现细节在将来的版本中保持不变。现在,他们使用HashSet
,但将来他们可能想要使用不同类型的集合。
答案 3 :(得分:2)
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));