【问题标题】:Create java stream with supplier lazyly懒惰地与供应商创建 java 流
【发布时间】:2018-05-22 11:03:37
【问题描述】:

是否可以使用 Java 8 流 API 创建在必要时才评估的流?

我是说。

我有一个处理元素列表的流,在其中一个中间操作(映射)中,我必须通过另一个流读取,并且我希望将该流放在另一个变量中,以便通过所有其他第一个流对象使用,但如果没有要处理的对象,我想避免处理第二个流。

我认为用代码检查更容易:

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);
}

我的疑问是关于第一个流的生成,我想根据我处理的列表返回流,但我只想在它被使用时这样做(并且对所有消息元素使用相同的)。

任何想法..?

【问题讨论】:

  • 第二个流的.map中的操作会导致异常。流的forEach 终端操作会被调用多次,这是不允许的。为什么不返回一个流,让调用者只在必要时运行.toArray
  • 你应该指定Function的类型参数,使用原始类型会禁用一些编译时类型检查。

标签: java java-stream lazy-sequences


【解决方案1】:

别担心,在您附加 terminal operation 之前,不会评估您的 transformationsToApply

中间操作返回一个新流。他们总是很懒惰; 执行诸如 filter() 之类的中间操作实际上并不 执行任何过滤,而是创建一个新流,当 遍历,包含初始流中匹配的元素 给定谓词。管道源的遍历直到 执行管道的终端操作。

【讨论】:

  • 并且处理后的流的值将用于所有迭代?还是每次都会计算?这是我的疑问,这就是我将其保存在变量中的原因。
  • 您在.map 中的表达式将导致异常将导致异常,因为流只能被消费一次。我建议你将transformationsToApply.toList 的结果存储到一个局部变量中,并在你的.map 方法中重用它
【解决方案2】:

流不是有状态的,所以没有简单的方法让它只在处理第一个元素时才做某事。在这种情况下,您可以检查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 流的问题,您需要先将其设为集合,然后才能对其进行多次迭代。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-15
    • 1970-01-01
    • 2021-01-08
    • 2012-11-04
    • 2013-05-14
    • 1970-01-01
    • 2011-12-31
    • 1970-01-01
    相关资源
    最近更新 更多