Java 8对空列表的流操作

39

我在想,Java 8的stream在空列表上会有什么行为。

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

这会是空列表还是null

我知道进行惰性传播,那么在这种情况下,调用是否会进入collect()方法,还是仅停留在stream()方法中?


2
说到另一个完全不同的观点,使用原始类型这个也无法编译...只是你也可以试一试。 - Naman
是的,实际上我想问的是特定的数据类型。但你提供的信息很有趣。现在这些东西都非常依赖于IDE。 - gaurav agarwal
为什么这个是-1呢 :/ - Chandresh Mishra
2个回答

55

collect是终端操作,所以必须进行评估。

当用collect(Collectors.toList())终止一个Stream流水线时,您总会得到一个输出List(永远不会得到null)。如果这个Stream是空的(无论是因为源流为空还是因为在终端操作之前过滤了所有元素),输出List也将为空。


8
你将得到一个空集合。如在文档中所解释的那样,collect执行对此流的元素使用Collector的可变减少操作。
可变减少操作是这样解释的:
可变减少操作将输入元素累积到可变结果容器(例如Collection或StringBuilder)中,因为它处理流中的元素。
如果原始输入为空或由于过滤操作,您将获得一个空集合。
感谢@Andy Turner的提示。
引用他的话:“toList()将累积到新列表中,这意味着它不会返回null。”
文档说明了Collectors.toList()的工作方式:
返回将输入元素累积到新List中的Collector。
我们可以从源代码中得到这个信息。
    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);
    }

它永远不会产生空输出,但是您仍然可以通过自定义Collector来获取空值,就像Andy所展示的那样。

1
虽然你在这里说的是正确的,但仍有可能出现收集器返回 null 的情况。例如,.collect(Collector.of(ArrayList::new, ArrayList::add, (a, b) -> a, a -> null))(或类似的代码)会返回 null。而 toList() 方法之所以不会返回 null,是因为它会将结果累加到一个新的列表中。 - Andy Turner
@AndyTurner,您的解释更好地阐述了收集机制。 - Lebecca
不要说 Collectors.toList(),而是尝试更通用地说 .collect() - Vishwa Ratna

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接