Collectors.toSet() 总是 return 一个 HashSet 吗?合约是什么?
Does Collectors.toSet() always return a HashSet ? What is the contract?
Javadoc 说
Returns a Collector that accumulates the input elements into a new
Set. There are no guarantees on the type, mutability, serializability,
or thread-safety of the Set returned; if more control over the
returned Set is required, use
toCollection(java.util.function.Supplier).
所以 Collectors.toCollection(HashSet::new)
似乎是避免此处出现问题的好主意 ()。
我的问题是,尽我所能,除了 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 声明没有保证,但这并不妨碍任何特定的实现总是return特定类型的集合。这只是设计人员说他们不想限制未来实现的功能。它没有说明当前的实现实际上做了什么。
换句话说,您发现了实现定义的行为(总是return一个HashSet
),但如果您指望它,您可能会遇到问题将来。
Collectors::toSet
返回的Set
的类型是一个实现细节。您不应依赖实现细节在未来的版本中保持不变。现在,他们使用 HashSet
,但将来他们可能想使用不同类型的集合。
当前 OpenJDK 的实现(以及 AFAIK,Oracle 的也是)确实总是 returns a HashSet
- 但没有 保证 的那个。如果您以某种方式假设 Collectors.toSet()
将 return 变成 HashSet
(例如,显式向下转换它),JDK 的未来版本很可能会改变这种行为并破坏您的代码).
我想你要找的是这个:
Collectors.toCollection(LinkedHashSet::new)
例如,未来的 java 版本可能 return 专门的不可变集实现比当前的 HashSet
实现更高效地读取并且消耗更少的内存,这实际上只是HashMap
的包装器。 Project valhalla 最终可能会导致此类优化。
他们甚至可能会根据数据量选择 return 不同的集合类型,例如如果事先知道只有零个或一个元素将被 returned.
,则为空集或单例集
因此,通过提供比基于当前实施的可能更少的保证,他们为未来的改进敞开了大门。
Javadoc 说
Returns a Collector that accumulates the input elements into a new Set. There are no guarantees on the type, mutability, serializability, or thread-safety of the Set returned; if more control over the returned Set is required, use toCollection(java.util.function.Supplier).
所以 Collectors.toCollection(HashSet::new)
似乎是避免此处出现问题的好主意 (
我的问题是,尽我所能,除了 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 声明没有保证,但这并不妨碍任何特定的实现总是return特定类型的集合。这只是设计人员说他们不想限制未来实现的功能。它没有说明当前的实现实际上做了什么。
换句话说,您发现了实现定义的行为(总是return一个HashSet
),但如果您指望它,您可能会遇到问题将来。
Collectors::toSet
返回的Set
的类型是一个实现细节。您不应依赖实现细节在未来的版本中保持不变。现在,他们使用 HashSet
,但将来他们可能想使用不同类型的集合。
当前 OpenJDK 的实现(以及 AFAIK,Oracle 的也是)确实总是 returns a HashSet
- 但没有 保证 的那个。如果您以某种方式假设 Collectors.toSet()
将 return 变成 HashSet
(例如,显式向下转换它),JDK 的未来版本很可能会改变这种行为并破坏您的代码).
我想你要找的是这个:
Collectors.toCollection(LinkedHashSet::new)
未来的 java 版本可能 return 专门的不可变集实现比当前的 HashSet
实现更高效地读取并且消耗更少的内存,这实际上只是HashMap
的包装器。 Project valhalla 最终可能会导致此类优化。
他们甚至可能会根据数据量选择 return 不同的集合类型,例如如果事先知道只有零个或一个元素将被 returned.
,则为空集或单例集因此,通过提供比基于当前实施的可能更少的保证,他们为未来的改进敞开了大门。