【问题标题】:Java 8 stream operation on empty list空列表上的 Java 8 流操作
【发布时间】:2019-02-03 09:21:53
【问题描述】:

我只是想知道 Java 8 stream 在空列表中的行为。

List<?> emptyList = new ArrayList<>();
List<?> processedList = emptyList.stream().collect(Collectors.toList());

这是空列表还是null

我知道 streams 会进行惰性传播,所以在这种情况下会调用 go to collect() 方法,还是会在 stream() 方法处结束?

【问题讨论】:

  • 还有一个不同的点,使用原始类型甚至无法编译......只是你也可以尝试一下。
  • 是的,实际上我的意思是要求特定的数据类型。但这是您在此处提供的有趣信息。这些天来,这类东西非常依赖 IDE。
  • 为什么是 -1 :/

标签: java java-8 java-stream


【解决方案1】:

collect 是终端操作,因此必须对其进行评估。

当使用collect(Collectors.toList()) 终止Stream 管道时,您将始终得到输出List(您永远不会得到null)。如果Stream 为空(由于流的源为空,或者由于流的所有元素在终端操作之前被过滤掉,它是否为空并不重要),输出@987654327 @ 也会为空。

【讨论】:

    【解决方案2】:

    您将获得一个空集合。 正如doc中解释的collect

    使用收集器对此流的元素执行可变归约操作。

    以及可变缩减

    可变归约操作在处理流中的元素时将输入元素累积到可变结果容器中,例如 Collection 或 StringBuilder。

    由于原始输入为空或由于过滤器操作,您将得到一个空集合。

    感谢@Andy Turner 的提示。

    toList() 会累积到一个新列表中,这意味着它不会返回 null。

    文档得到了 Collectors.toList() 的解释:

    返回一个收集器,将输入元素累积到一个新的列表中。

    我们可以从源码中得到

        public static <T>
        Collector<T, ?, List<T>> toList() {
            return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                                       (left, right) -> { left.addAll(right); return left; },
                                       CH_ID);
        }
    

    它永远不会产生空输出,但您仍然可以使用自定义收集器获得空值,如 Andy 所示。

    【讨论】:

    • 虽然您在此处所说的是正确的,但没有什么能阻止收集器产生 null。例如,.collect(Collector.of(ArrayList::new, ArrayList::add, (a, b) -&gt; a, a -&gt; null))(或类似的)would yield null。事实上,toList() 会累积到一个新列表中,这意味着它不会返回 null。
    • @AndyTurner 你对收集机制的解释是正确的。
    • 不要说Collectors.toList(),而是尽量笼统地说.collect()
    猜你喜欢
    • 2016-10-09
    • 1970-01-01
    • 1970-01-01
    • 2019-07-02
    • 2015-07-07
    • 1970-01-01
    • 2019-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多