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

Chr*_*ett 6 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);
Run Code Online (Sandbox Code Playgroud)

编译期间生成以下错误:

列表namesAsList = names.collect(() - > new ArrayList(),List :: add,List :: add); ^(参数不匹配;无效方法引用不兼容类型:ArrayList不能转换为int)其中R,T是类型变量:R extends方法中声明的对象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);
Run Code Online (Sandbox Code Playgroud)

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

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

Grz*_*rek 7

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

List<String> namesAsList = names
  .collect(ArrayList::new, List::add, List::addAll);
Run Code Online (Sandbox Code Playgroud)

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


此外,我假设您仅为研究目的实施此操作.如果你想收集Stream到a List,你可以简单地使用:

.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

如果你想收集你StreamArrayList明确,你可以去:

.collect(Collectors.toCollection(ArrayList::new));
Run Code Online (Sandbox Code Playgroud)

  • 您仍然可以使用`List :: add`和`List :: addAll`,然后,该语句仍然适合单行;-) (3认同)

Eug*_*ene 6

问题在于combiner,特别是:List::add应该真的List::addAll.

或者更像这样的可读性:

List<String> namesAsList = names.collect(
            () -> new ArrayList<>(), 
            List::add, 
            List::addAll);
Run Code Online (Sandbox Code Playgroud)

当你不确定btw时,你可以用lambda表达式重写它:

List<String> namesAsList = names.collect(
            () -> new ArrayList<>(),
            List::add,
            (List<String> left, List<String> right) -> {
                left.addAll(right);
            });
Run Code Online (Sandbox Code Playgroud)

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

 List<String> namesAsList = names.collect(
            ArrayList::new,
            List::add,
            List::addAll);
Run Code Online (Sandbox Code Playgroud)

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

List<String> namesAsList = names.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

唯一的问题是规范可以自由地改变它(除了返回任何其他 ),所以它可以写成:ListArrayList

 List<String> namesAsList = names.collect(Collectors.toCollection(ArrayList::new));
Run Code Online (Sandbox Code Playgroud)

  • @pivovarit他们但不一致;) (2认同)