当前位置: 首页 > 知识库问答 >
问题:

收集器的合并器功能可以用于顺序流吗?

谢高峯
2023-03-14

示例程序:

public final class CollectorTest
{
    private CollectorTest()
    {
    }

    private static <T> BinaryOperator<T> nope()
    {
        return (t, u) -> { throw new UnsupportedOperationException("nope"); };
    }

    public static void main(final String... args)
    {
        final Collector<Integer, ?, List<Integer>> c
            = Collector.of(ArrayList::new, List::add, nope());

        IntStream.range(0, 10_000_000).boxed().collect(c);
    }
}

所以,为了简化这里的问题,没有最终的转换,所以得到的代码非常简单。

共有1个答案

贺轶
2023-03-14

正如前面@Markotopolnik和@Duncan的评论所指出的,不能保证调用顺序模式下的collector.Combiner()来产生简化的结果。事实上,Java doc在这一点上有点主观,这可能导致不恰当的解释。

(...)并行实现将对输入进行分区,为每个分区创建结果容器,将每个分区的内容累加为该分区的子结果,然后使用组合器函数将子结果合并为组合结果。

根据NoBlogDefFound的说法,组合器仅在并行模式下使用。见以下部分报价:

public final class CollectorTest
{
    private CollectorTest()
    {
    }

    private static <T> BinaryOperator<T> nope()
    {
        return (t, u) -> { throw new UnsupportedOperationException("nope"); };
    }

    public static void main(final String... args)
    {

        final Collector<Integer, ?, List<Integer>> c =
                Collector
                    .of(ArrayList::new, List::add, nope());

        // approach sequential
        Stream<Integer> sequential = IntStream
                .range(0, 10_000_000)
                .boxed();

        System.out.println("isParallel:" + sequential.isParallel());
        sequential
                .collect(c);

        // approach parallel
        Stream<Integer> parallel = IntStream
                .range(0, 10_000_000)
                .parallel()
                .boxed();

        System.out.println("isParallel:" + parallel.isParallel());
        parallel
                .collect(c);
    }
}
isParallel:false
isParallel:true
Exception in thread "main" java.lang.UnsupportedOperationException: nope
    at com.stackoverflow.lambda.CollectorTest.lambda$nope$0(CollectorTest.java:18)
    at com.stackoverflow.lambda.CollectorTest$$Lambda$3/2001049719.apply(Unknown Source)
    at java.util.stream.ReduceOps$3ReducingSink.combine(ReduceOps.java:174)
    at java.util.stream.ReduceOps$3ReducingSink.combine(ReduceOps.java:160)

因此,根据这个结果我们可以推断收集器的组合器只能通过并行执行来调用。

 类似资料:
  • 问题内容: 示例程序: 因此,为简化起见,没有最终转换,因此生成的代码非常简单。 现在,产生一个顺序流。我只是将结果装箱到s中,然后将其收集到中。很简单 而且,无论我运行此示例程序多少次,都不会成功,这意味着永远不会调用我的虚拟组合器。 我有点期望,但是后来我已经误解了流,以至于我不得不问这个问题… 可以将的组合时,流过被称为 保证 是连续的? 问题答案: 仔细阅读ReduceOps.java中的

  • 问题内容: 我真的很喜欢Java 8流和Guava的不可变集合,但是我不知道如何将两者一起使用。 例如,如何实现将流结果收集到ImmutableMultimap中的Java 8 Collector? 优点:我希望能够提供键/值映射器,类似于Collectors.toMap()的工作方式。 问题答案: 从21版开始,您可以

  • 在jdk8中,Stream提供带有、和的功能 我在注释中看到了将String Stream转换为String的示例,但我很困惑组合器在函数签名中的用途。我认为在累加器中,新元素已添加到结果大陆? 我尝试给组合器一个null值,但我得到了一个null指针异常。

  • 问题内容: 我不了解以下方法的第三个参数的实用程序: 从javaDoc: 产生的结果等于: 如您所见,该参数未使用。例如,以下代码将字符串累积到ArrayList中: 但我期望这样: 问题答案: 在使用时,你的是平行的,因为在这种情况下,多个线程收集的元素到最终输出的子列表,并且这些子列表必须被组合以产生最终的。

  • 问题内容: 在上面的代码中,我可以期望中的名称顺序始终与中的顺序相同吗? 问题答案: 是的,只要您没有将并行流显式转换为模式,即使您正在使用并行流,也可以期望这样做。 顺序永远不会在顺序模式下更改,但可能会在并行模式下更改。流变得无序: 如果您通过调用将其明确转换为无序模式 如果流源报告它是无序的(例如,流是无序的,因为顺序取决于实现,因此您不能依赖它) 如果您使用的是无序终端操作(例如,进行操作