java – 连续流操作是否有副作用?
作者:互联网
我正在尝试将有限数量的值流式传输到集合中,但我需要在应用限制之前验证它们是否是新元素.例如:
Set<Integer> destination = ...
Set<Integer> source = ...
source.stream()
.filter(i -> !destination.contains(i))
.limit(10)
.forEach(destination::add);
但冗余的contains()检查让我烦恼,因为add()可以添加元素并报告它是否是集合的新内容.所以我想这样做:
source.stream()
.filter(destination::add)
.limit(10)
.forEach(i -> {}); // no-op terminal operation to force evaluation
忽略hacky终端操作,存在使用具有副作用的过滤操作的问题,这通常是不鼓励的.我理解为什么在并行流上使用带有副作用的map()和filter()是不安全的.我的问题是,在顺序流上是否可以接受,就像在这种情况下一样?如果没有,为什么不呢?
解决方法:
副作用和顺序流没有根本问题,但上面的第二个实现是无效的,因为流API不保证每个元素将依次在每个元素上执行.
在第二种实现中,在应用限制之前,可以向目的地添加10个以上的元素.你的无操作forEach只会看到10,但你最终可能会得到更多.
除了流之外,java还有像for和while这样的循环结构,可以很容易地表达这样的东西.
如果必须使用流,可以这样做:
int maxSize = destination.size()+10;
source.stream().allMatch(x -> destination.size()<maxsize && (destination.add(x)||true));
一旦谓词返回false,allMatch将停止迭代.
标签:java,java-stream,side-effects 来源: https://codeday.me/bug/20190527/1166110.html