懒惰地与供应商一起创建java流

时间:2018-05-22 11:03:38

标签: java java-stream lazy-sequences

使用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>

任何想法......?

2 个答案:

答案 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流的问题,你需要先将它作为一个集合,然后才能多次迭代它。