提问人:user504909 提问时间:7/1/2022 最后编辑:Alexander Ivanchenkouser504909 更新时间:7/1/2022 访问量:611
如何在应用收集之前从流中删除 Null 元素?
How to delete Null-elements from the Stream before applying collect?
问:
我的流函数有时会返回,当我收集它们时如何删除该返回?null
null
versions.stream().map(vs->{
if(vs.matches("^matched string$")) {
...
return new VersionNumber(tmp[0], tmp[1], tmp[2]));
}
return null;
}).flatMap(Optional::stream).collect(Collectors.toList());
对于这个流函数,如果全部匹配是,我的意思是如果方法里面的所有函数都会上升。false
map()
NullPointException
如何使此流不产生异常,当所有元素都返回空列表或?null
null
答:
您可以之后进行筛选
versions.stream().map(vs->{
if(vs.matches("^matched string$")) {
...
return new VersionNumber(tmp[0], tmp[1], tmp[2]));
}
return null;
}).filter(Objects::nonNull).flatMap(Optional::stream).collect(Collectors.toList());
但越早过滤越明智
versions.stream().filter(vs -> vs.matches("^matched string$"))
.map(vs->{
...
return new VersionNumber(tmp[0], tmp[1], tmp[2]));
}).flatMap(Optional::stream).collect(Collectors.toList());
评论
flatMap(Optional::stream)
从 java 16 开始,还有 Stream.mapMulti
:
返回一个流,该流包含将此流的每个元素替换为多个元素(特别是零个或多个元素)的结果。
(强调我的)
使用这个,你的例子就变成了:
versions.stream().mapMulti((vs, consumer)->{
if(vs.matches("^matched string$")) {
...
consumer.accept(new VersionNumber(tmp[0], tmp[1], tmp[2]));
}
}).collect(Collectors.toList());
请注意,null 值根本不会在下游发出,因此不需要筛选或中间流进行平面映射。
另一个例子:
record A(String name, long count) {}
public static void main(String[] args) {
Stream.of(new A("apple", 1), new A("orange", 3), new A("banana", 0))
.mapMulti((bucket, consumer) -> {
for (int i = 0; i < bucket.count(); i++) {
consumer.accept(bucket.name());
}
})
.forEachOrdered(System.out::println);
}
指纹:
apple
orange
orange
orange
3个橙子,但没有香蕉
如果所有匹配都是假的,我的意思是如果 .map 方法中的所有函数,它将上升一个
NullPointException
由于你得到的是一个,这意味着你的代码可以编译和运行。因此,我假设操作中的“代码”不是您的实际代码,因为我们不能将 of 中的元素视为可选元素。NullPointerException
map()
Stream<VersionNumber>
flatMap(Optional::stream)
仅当 preceding 生成 类型的结果时,才不会导致编译错误。map()
Optional<VersionNumber>
因此,我的建议很简单:永远不要返回来代替可选。当可选对象可能是 时,这是完全错误的,它应该包含一个值或为空,但它永远不应该是。null
null
null
正如 @Andy Thomas 在评论中指出的那样,如果里面的代码真的像 .在这种情况下,用 an 包装 的结果将是对 optional 的误用。返回 instance 或 。然后应用过滤器:Optional
map()
new VersionNumber(tmp[0], tmp[1], tmp[2]));
map()
Optional
VersionNumber
null
.map(vs -> {
if (vs.matches("^matched string$")) {
...
return new VersionNumber(tmp[0], tmp[1], tmp[2]);
}
return null;
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
只有当在地图中您实际上没有像您所显示的那样创建时,您才必须求助于可选的使用,但是,例如,进行 API 调用,如果某些条件是肉,则返回 a。VersionNumber
Optional<VersionNumber>
.map(vs -> {
if (vs.matches("^matched string$")) {
...
return getVersionNumber(tmp[0], tmp[1], tmp[2]); // method returing Optional<VersionNumber>
}
return Optional.empty();
})
.flatMap(Optional::stream)
.collect(Collectors.toList());
在这种情况下,无需应用筛选。 当在 empty optional 上调用时,会生成一个空流。Optional.stream()
评论
flatMap(Optional::stream)
评论
map()
VersionNumber
new VersionNumber()
flatMap(Optional::stream)
Optional<VersionNumber>
flatMap(Optional::stream)