为什么这个java 8流操作求值为Object而不是List 或只是List?

我正在使用3d派对库,他们返回缺少类型规范的集合(例如public List getFoo(); ),并且我正在尝试转换它们的返回类型并返回具有适当类型的列表。

我创建了一个演示问题的简单示例。 例如

编辑原始问题将l2声明为ArrayList而不是List ,现在已更正。

 import java.util.List; import java.util.ArrayList; import java.util.stream.Collectors; public class Foo { public static void main(String[] args) { ArrayList l = new ArrayList(); l.add(1); l.add(2); List l2 = l.stream().map(Object::toString).collect(Collectors.toList()); } } 

这无法编译。

 $ javac Foo.java Foo.java:10: error: incompatible types: Object cannot be converted to List List l2 = l.stream().map(Object::toString).collect(Collectors.toList()); ^ 1 error 

如果我稍微修改程序,那么它编译,我可以检查流/收集操作的返回类型。 它“有效”,虽然我不得不施展结果。

例如

 import java.util.ArrayList; import java.util.stream.Collectors; public class Foo { public static void main(String[] args) { ArrayList l = new ArrayList(); l.add(1); l.add(2); Object l2 = l.stream().map(Object::toString).collect(Collectors.toList()); System.out.println(l2.getClass()); } } 

运行此节目……

 $ javac Foo.java Note: Foo.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. $ java Foo class java.util.ArrayList 

正如所料。

因此,Collectors.listCollector()在运行时做了正确的事情,但是这是预期的编译时行为吗? 如果是这样,它周围是否有“正确”的方式?

stream()map()collect()和所有其他流方法依赖于通用类型来使事情顺利运行。 如果使用原始类型作为输入,则所有generics都将被删除,并且所有内容都将变为原始类型。 例如,如果您有List ,则调用stream()方法会为您提供Stream类型的对象。

但是如果你从一个原始类型List ,那么调用stream()会给你一个原始类型Stream的对象。

map()方法有这个声明:

   Stream map(Function mapper) 

但是因为它是在原始Stream上调用的,所以就好像声明一样

  Stream map(Function mapper) 

所以调用map()的结果只是一个Streamcollect()的签名用generics填充:

   R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner) 

当使用原始类型调用时,它将被删除

  Object collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner) 

所以当流源是原始类型时,流管道的返回类型是Object 。 显然这与ArrayList不兼容,并且您收到编译错误。

要解决此问题,请尽快将您的类型带入通用世界。 这可能涉及未经检查的强制转换,您应该抑制警告。 当然,只有在您确定返回的集合包含仅具有预期类型的​​对象时才执行此操作。

另外,正如Hank D指出的那样, toList()收集器返回一个List ,而不是一个ArrayList 。 您可以将返回值分配给List类型的变量,也可以使用toCollection()显式创建ArrayList的实例。

以下是包含以下修改的代码:

  @SuppressWarnings("unchecked") ArrayList l = (ArrayList)getRawArrayList(); l.add(1); l.add(2); ArrayList l2 = l.stream() .map(Object::toString) .collect(Collectors.toCollection(ArrayList::new)); 

Collectors.toList()返回List,而不是ArrayList。 这将编译:

 public static void main(String[] args) { ArrayList l = getRawArrayList(); List l2 = l.stream().map(Object::toString).collect(Collectors.toList()); }