为了账号安全,请及时绑定邮箱和手机立即绑定

为什么我在 collect() 之后调用 stream() 时会得到 Stream<Object>?

为什么我在 collect() 之后调用 stream() 时会得到 Stream<Object>?

鸿蒙传说 2021-10-17 15:43:26
考虑以下未编译的示例:List<Integer> list = Arrays.asList(1, 2, -3, 8);        list.stream()                .filter(x -> x > 0)                .collect(ArrayList::new, ArrayList::add, ArrayList::addAll)                .stream() // Stream<Object>                .map(x -> x * 2)                .forEach(System.out::println);如果我更换.collect(ArrayList::new, ArrayList::add, ArrayList::addAll)和.collect(Collectors.toList())代码将被编译。所以问题是我如何编写collect()供应商和累加器(我需要它)才能stream()在它之后调用 a ?
查看完整描述

1 回答

?
慕少森

TA贡献2019条经验 获得超9个赞

看来您已经对ArrayList构造函数进行了原始方法引用ArrayList::new。


类型参数不是通过以下方式推断的:


.collect(ArrayList::new, ArrayList::add, ArrayList::addAll)

所述的3个参数的过载collect预计3个参数,第一个是一个Supplier<R>。此时,collect方法的类型参数R与此处的Twhich之间没有联系Integer。推断这一点的唯一方法是通过第二个参数 a BiConsumer<R, ? super T>。在这里,您有ArrayList::add,这使编译器也无法进行推断R。


您必须提供R第一个参数中的内容,即供应商。您可以向类提供显式类型参数以在方法引用上创建。


.collect(ArrayList<Integer>::new, ArrayList::add, ArrayList::addAll)

这将编译,并且输出符合预期:


2

4

16

当您使用 时Collectors.toList(),您只提供一个参数。


public static <T> Collector<T,?,List<T>> toList()


在这里,只有一个类型参数T,因此编译器可以正确推断出这T是Integer,因此List<Integer>创建了 a ,从而允许代码编译。Collector返回的绑定T到的类型参数List<T>,允许编译器执行类型推断。


请注意,这只是首先需要的,因为没有目标类型可以帮助进行类型推断;您继续进行流操作并System.out.println在最后调用,这可以采用Object.


如果你有这个代码:


List<Integer> modified = list.stream()

            .filter(x -> x > 0)

            .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);

然后目标类型推断将提供Integer给 的类型参数ArrayList::new。这也编译。


查看完整回答
反对 回复 2021-10-17
  • 1 回答
  • 0 关注
  • 216 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信