Java的Stream.collect()可以返回null吗?

时间:2018-05-09 15:12:57

标签: java java-stream

JavaDoc for Stream.collect()表示返回the result of the reduction。这并没有告诉我这样的代码是否可以为filteredList返回null:

List<String> filteredList = inputList.stream().
filter(c -> c.getSomeBoolean()).
flatMap(c -> {
  List<String> l = new ArrayList<String>();
  l.add(c.getSomething());
  l.add(c.getSomethingElse());
  return l.stream();
}).
filter(s -> StringUtils.isNotBlank(s)).
collect(Collectors.toList());

我希望如果它可以返回null,那么它将返回Optional,但它也没有说明。

是否记录Stream.collect()是否可以返回null?

6 个答案:

答案 0 :(得分:14)

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

正如您所看到的,ArrayList::new被用作您商品的容器。

修改

我在这里看到了很多疑问,所以我阅读了JavaDoc并与您分享:

来自Collector的JavaDoc:

  

公共接口收集器

     

可变减少操作   可选地将输入元素累积到可变结果容器中   将累积结果转换为最终表示   所有输入元素都已处理完毕。减少操作可以   顺序或并行执行。

     

收集器由四个一起工作的函数指定   将条目累积到可变结果容器中,并且可选地   对结果执行最终转换。他们是:

     
      
  • 创建新的结果容器(供应商())

  •   
  • 将新数据元素合并到结果容器(accumulator())

  •   
  • 将两个结果容器合并为一个(合并器())
  •   
  • 对容器执行可选的最终转换(finisher())
  •   

  

使用收集器顺序实现减少   使用供应商功能创建单个结果容器,并且   为每个输入元素调用一次累加器函数。一个   并行实现会对输入进行分区,创建结果   每个分区的容器,累积每个分区的内容   分区为该分区的子结果,然后使用   合并器函数将子结果合并为一个组合结果。

因此,只要您不执行组合函数返回null等奇怪的操作,Collector始终使用您提供的mutable container函数返回至少supplier

如果一个实现能够返回null容器,我认为这是违反直觉的。

答案 1 :(得分:5)

这不取决于Stream.collect,而取决于个人CollectorCollectors.toList()将返回空的ArrayList

也就是说,在某些情况下,没有人不能使用奇怪的Collector来返回null:

.collect(
    Collector.of(
        ArrayList::new,
        ArrayList::add,
        (a, b) -> {
            a.addAll(b);
            return a;
        },
        a -> a.isEmpty() ? null : a  // finisher replaces empty list with null
    )
);

所以Collector是您需要记住检查的事情。我相信所有Collectors available out-of-the-box都会返回空集合,正如您所期望的那样。

答案 2 :(得分:2)

我认为文档的这一部分说它不能为空:

  

返回一个收集器,用于将输入元素累积到 ne w中   的列表

精彩集锦由我添加。我认为这个新列表意味着什么不是空的。

我开始检查ReferencePipeline.collect()以检查实际实施是否属实。不幸的是,这是徒劳的尝试。这里有很多案例,就像它是平行的吗?它是在forEach之后吗?等

答案 3 :(得分:1)

这是收集器依赖的。你正在使用的那个(Collectors.toList())返回一个空列表。

答案 4 :(得分:0)

没有collect绝不会返回null,为了检查使用isEmpty()而不是null

答案 5 :(得分:0)

您可以使用Collectors::collectingAndThen将collect()结果传递给Function<T,R>Function<T,R>的返回值将是collect()的返回值。

List<String> filteredList = inputList.stream()
 .filter(c -> c.isActive())
 .collect(Collectors.collectingAndThen(Collectors.toList(), c -> !c.isEmpty()?c:null));