使用Java 8流API可以创建在需要之前不进行评估的Stream吗?
我的意思是。
我有一个处理元素列表的流,在其中一个中间操作(map)中我必须读取另一个流,我想让另一个变量中的Stream用于所有其他第一个流对象,但如果没有要处理的对象,我想避免处理第二个流。
我认为使用代码检查更容易:
Message[] process(@Nullable Message[] messages) {
Stream<Function> transformationsToApply =
transformations
.stream()
.filter(transformation -> transformationIsEnabled(transformation.getLeft()))
.map(Pair::getRight);
return Arrays.stream(messages != null ? messages : new Message[0])
.filter(Objects::nonNull)
.map(agentMessage -> {
transformationsToApply.forEach(transformation -> processMessage(transformation, agentMessage));
return agentMessage;
})
.toArray(Message[]::new);
}
我的疑问是关于第一个流生成,我想根据我处理的列表返回流,但我只想要做它将被使用(并且对所有消息元素使用相同)。< / p>
任何想法......?
答案 0 :(得分:2)
不用担心,在您附加terminal operation之前,我们不会评估您的transformationsToApply
。
中间操作返回一个新流。他们总是懒惰; 执行诸如filter()之类的中间操作实际上并不是这样 执行任何过滤,而是创建一个新的流,当时 遍历,包含匹配的初始流的元素 给出谓词。直到管道源的遍历才开始 执行管道的终端操作。
答案 1 :(得分:1)
Streams不是有状态的,所以只有在处理第一个元素时才能让它做某事。在这种情况下,您可以检查messages
参数并在没有任何操作的情况下提前返回:
Message[] process(@Nullable Message[] messages) {
if (messages == null || messages.length == 0) return new Message[0];
List<Function> transformationsToApply = transformations.stream()
.filter(transformation -> transformationIsEnabled(transformation.getLeft()))
.map(Pair::getRight)
.collect(Collectors.toList());
return Arrays.stream(messages)
.filter(Objects::nonNull)
.map(agentMessage -> {
transformationsToApply.forEach(transformation -> processMessage(transformation, agentMessage));
return agentMessage;
})
.toArray(Message[]::new);
}
我还修复了重用transformationsToApply
流的问题,你需要先将它作为一个集合,然后才能多次迭代它。