使用collect Stream方法时,参数不匹配

时间:2017-07-25 08:30:38

标签: java java-8 java-stream

以下代码:

names = Arrays.asList("A","B","C").stream();
List<String> namesAsList = names.collect(() -> new ArrayList<String>(),List::add,List::add);
System.out.println("Individual Strings put into a list: " + namesAsList);

在编译期间生成以下错误:

  

列出namesAsList = names.collect(() - &gt; new   的ArrayList(),列表::添加,列表::补充);                                                   ^(参数不匹配;无效方法引用不兼容类型:ArrayList不能   转换为int)其中R,T是类型变量:R扩展Object   在方法collect(Supplier,BiConsumer,BiConsumer)中声明T扩展在接口Stream 1中声明的Object   错误

当我修改代码以删除泛型时,代码将使用未经检查的表达式编译警告:

Stream<String> names = Arrays.asList("A","B","C").stream();
List<String> namesAsList = names.collect(() -> new ArrayList(),List::add,List::add);
System.out.println("Individual Strings put into a list: " + namesAsList);

为什么我会收到此错误?我不认为这个问题与int有关。

如果答案可能包括解决问题的方法,我将不胜感激,所以我可以自己学习如何解决这些问题。

2 个答案:

答案 0 :(得分:7)

combiner传递的方法引用并不适合。 尝试:

List<String> namesAsList = names
  .collect(ArrayList::new, List::add, List::addAll);

您传递了List::add,编译器正在尽力将其解释为BiConsumer类型的组合器实例。因此,奇怪的参数不匹配错误。

此外,我假设您仅为研究目的实施此操作。如果您想将Stream收集到List,只需使用:

即可
.collect(Collectors.toList());

如果您想特别向Stream收集ArrayList,您可以选择:

.collect(Collectors.toCollection(ArrayList::new));

答案 1 :(得分:6)

问题出在combiner,具体来说:List::add应该是List::addAll

或更具可读性:

List<String> namesAsList = names.collect(
            () -> new ArrayList<>(), 
            List::add, 
            List::addAll);

当你不确定btw:

时,你可以用lambda表达式重写它
List<String> namesAsList = names.collect(
            () -> new ArrayList<>(),
            List::add,
            (List<String> left, List<String> right) -> {
                left.addAll(right);
            });

请注意,还有其他问题,例如() -> new ArrayList<String>(),编译器会在此处推断出类型,因此不需要<String>,如下所示:() -> new ArrayList<>()。此外,这也可以转换为方法参考:ArrayList::new,所以最终它会更简单:

 List<String> namesAsList = names.collect(
            ArrayList::new,
            List::add,
            List::addAll);

这个btw与Collectors.toList内部做的相同,所以更进一步,这可以简化为:

List<String> namesAsList = names.collect(Collectors.toList());

唯一的问题是规范可以自由更改(除了List之外还返回任何其他 ArrayList),因此可以写成:

 List<String> namesAsList = names.collect(Collectors.toCollection(ArrayList::new));