Cho*_*s-2 11 java null java-8 java-stream
该Set接口不承诺实现是否允许null元素.每个实现都应该在其文档中声明.
Collectors.toSet()承诺回报的实现Set,但明确地让"无担保的类型,可变性,串行化,或线程安全Set返回".没有提到空安全性.
目前执行Collectors.toSet()中的OpenJDK总是使用HashSet,允许null元素,但是这可能在未来改变和其他实施方式可以做出不同的.
如果某个Set实现禁止null元素,它会NullPointerException在不同时间抛出,特别是在尝试时add(null).似乎如果Collectors.toSet()决定使用null不容忍的Set实现,则调用stream.collect(Collectors.toSet())一个Stream stream将抛出.规范collect没有列出任何异常,也没有列出任何Collector方法的规范.这可能表明该collect调用允许空值stream,但另一方面,目前尚不清楚这是否实际上意味着很多,因为NullPointerException未经检查的异常并不严格必须列出.
在其他任何地方都明确指出了吗?特别是,以下代码保证不抛出?它有保证返回true吗?
import java.util.stream.*;
class Test {
public static boolean setContainsNull() {
return Stream.of("A", "list", "of", null, "strings")
.collect(Collectors.toSet())
.contains(null);
}
}
Run Code Online (Sandbox Code Playgroud)
如果没有,那么我假设在使用Collectors.toSet()或准备好处理之前我们应该始终确保流不包含空值NullPointerException.(这是例外单独够有关系吗?)或者,当这是不可接受的或硬的,我们可以要求使用类似的代码一组特定的实现Collectors.toCollection(HashSet::new).
编辑:有一个现有的问题,听起来表面上相似,这个问题被关闭作为一个假设的副本.但是,相关问题根本没有解决Collectors.toSet().此外,该问题的答案构成了我的问题的基本假设.那个问题问:流中是否允许空值?是.但是当通过标准收集器收集包含空值的(完全允许的)流时会发生什么?
故意未指定的行为(如"类型,可变性,可串行性或线程安全性")和未指定的行为(如支持)之间存在差异null.
每当一个行为被指定时,参考实现的实际行为往往成为事实的问题,即使由于兼容性限制而抵消原始意图,以后也无法改变,或者至少如果没有一个有力的理由.
请注意,虽然Set未使用返回真正不可变或不可序列化的保留权限,但仅仅因为Java 8发行版中null不存在此类型,即使没有足够的哈希映射类型,也可以强制执行非行为,比如groupingBy禁止null密钥,但也没有说明.
进一步注意,虽然groupingBy收集器故意拒绝null其实现代码中的密钥,但是toMap实际行为如何成为合同的一部分的一个很好的例子.在Java 8中,toMap允许null键但拒绝null值,只是因为它调用Map.merge具有该行为的键.看来,这首先不是预期的行为.现在,在Java 9中,toMap没有合并功能的收集器不再使用Map.merge(JDK-8040892,请参阅此答案),但故意拒绝null收集器代码中的值,以与先前版本行为兼容.仅仅因为从未说过该null行为是故意未指明的.
因此,Collectors.toSet()(同样Collectors.toList())现在允许null两个主要Java版本的值,并且没有规范说你不能认为这是理所当然的,所以你可以确定这将来不会改变.
| 归档时间: |
|
| 查看次数: |
1439 次 |
| 最近记录: |