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

Dea*_*lze 12 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());
Run Code Online (Sandbox Code Playgroud)

我希望如果它可以返回null然后它将返回Optional,但它也没有说.

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

Mạn*_*yễn 20

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);
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的那样,ArrayList::new它被用作物品的容器.

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

来自Collector的 javadoc

公共接口收集器

可变缩减操作,将 输入元素累积到可变结果容器中,可选地在处理完所有输入元素后将累积结果转换为最终表示.还原操作可以顺序执行或并行执行.

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

  • 创建新的结果容器(supplier())

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

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

使用收集器顺序实现缩减将 使用supplier函数创建单个结果容器,并为每个输入元素调用累加器函数一次.并行实现将对输入进行分区,为每个分区创建结果 容器,将每个分区的内容累积到该分区的子结果中,然后使用组合器函数将子结果合并为组合结果.

所以只要你不做奇怪的事情,比如组合函数返回null,null总是至少返回一个Collector使用你提供的mutable container函数.

而且我认为如果一个实现可以返回supplier容器,这是非常反直觉的.


AHH*_*HHP 13

您可以使用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));
Run Code Online (Sandbox Code Playgroud)


Mic*_*ael 9

这不取决于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
    )
);
Run Code Online (Sandbox Code Playgroud)

因此,这Collector是您需要记住检查的东西。我相信,所有Collectors可用的即用型包装都将返回空集合,正如您所期望的那样。