gpt4 book ai didi

java-8 - 为什么 Java Streams 没有中间组合操作?

转载 作者:行者123 更新时间:2023-12-02 11:47:43 25 4
gpt4 key购买 nike

注意:我不一定要寻找下面描述的具体示例问题的解决方案。我真的很感兴趣为什么这在 java 8 中不可能开箱即用。

<小时/>

Java 流是惰性的。最后他们只有一个终端操作。
我的解释是,这个终端操作将通过流提取所有值。没有任何中间操作可以做到这一点。为什么没有中间操作可以通过流拉入任意数量的元素?像这样的事情:

stream
.mapMultiple(this::consumeMultipleElements) // or groupAndMap or combine or intermediateCollect or reverseFlatMap
.collect(Collectors.toList());

当下游操作尝试使流前进一次时,中间操作可能会尝试使上游多次前进(或根本不前进)。

我会看到几个用例:
(这些只是示例。因此您可以看到,当然可以处理这些用例,但它“不是流式处理方式”,并且这些解决方案缺乏 Streams 所具有的理想的惰性属性。)

  • 将多个元素组合成一个新元素,以便向下传递到流的其余部分。 (例如,配对 (1,2,3,4,5,6) ➔ ((1,2),(3,4),(5,6)))

    // Something like this,
    // without needing to consume the entire stream upfront,
    // and also more generic. (The combiner should decide for itself how many elements to consume/combine per resulting element. Maybe the combiner is a Consumer<Iterator<E>> or a Consumer<Supplier<E>>)
    public <E, R> Stream<R> combine(Stream<E> stream, BiFunction<E, E, R> combiner) {
    List<E> completeList = stream.collect(toList());
    return IntStream.range(0, completeList.size() / 2)
    .mapToObj(i -> combiner.apply(
    completeList.get(2 * i),
    completeList.get(2 * i + 1)));
    }
  • 确定流是否为空(将流映射到可选的非空流)

    // Something like this, without needing to consume the entire stream
    public <E> Optional<Stream<E>> toNonEmptyStream(Stream<E> stream) {
    List<E> elements = stream.collect(toList());
    return elements.isEmpty()
    ? Optional.empty()
    : Optional.of(elements.stream());
    }
  • 拥有一个不会终止流的惰性迭代器(允许基于更复杂的逻辑跳过元素,然后只是skip(long n))。

    Iterator<E> iterator = stream.iterator();
    // Allow this without throwing a "java.lang.IllegalStateException: stream has already been operated upon or closed"
    stream.collect(toList());

当他们设计 Streams 及其周围的一切时,他们是否忘记了这些用例,或者是否明确忽略了这一点?
我知道在处理并行流时,这些可能会产生意想不到的结果,但在我看来,这是一个可以记录的风险。

最佳答案

您想要的所有操作实际上都可以在 Stream API 中实现,但不是开箱即用的。

将多个元素组合成元素对 - 为此,您需要一个自定义 Spliterator。这是Tagir Valeev这样做。他有一个名为 StreamEx 的绝对野兽库,它可以完成许多其他开箱即用不支持的有用的事情。

我不明白你的第二个例子,但我打赌它也是可行的。

skip 到更复杂的操作在 java-9 中通过 dropWhiletakeWhile 进行,需要 谓词作为输入。

请注意,当您说没有任何中间操作可以做到这一点时,这是不准确的 - 有 sorteddistinct 正是这样做的。否则他们就无法工作。还有 flatMap 具有类似的作用,但它更像是一个错误。

还有一件事是并行流的中间操作没有定义的顺序,因此这样的有状态中间操作将具有并行流的未知条目。另一方面,您始终可以选择滥用以下内容:

List<Something> list = Collections.synchronizedList()
.map(x -> {
list.add(x);
// your mapping
})

如果我是你并且真的认为我是否需要这样做,我就不会这样做,但以防万一......

关于java-8 - 为什么 Java Streams 没有中间组合操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47574161/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com