有效的流的收集方法供应商

Ash*_*ngh 5 java arraylist java-8 java-stream collectors

我只是想尝试创建一些类似于Collectors.toList()我自己的东西,但似乎没有用

import java.util.ArrayList;

public class ShipmentTracingDTO {

boolean destination = false;

public ShipmentTracingDTO(Boolean destination) {
    this.destination = destination;
}

public ShipmentTracingDTO() {
}

public static void main(String[] args) {
    ArrayList<ShipmentTracingDTO> tracings = new ArrayList<>();
    tracings.add(new ShipmentTracingDTO(true));
    tracings.add(new ShipmentTracingDTO(true));
    tracings.add(new ShipmentTracingDTO(false));
    tracings.add(new ShipmentTracingDTO(false));
    ArrayList<ShipmentTracingDTO> newTracings = new ArrayList<>();

// Error coming for ArrayList::new : The constructed object of type ArrayList is 
//incompatible with the descriptor's return type: R

    tracings.stream().collect(ArrayList::new, (left, right) -> left.add(right), (left, right) -> {
        left.addAll(right);
        return left;
    });
}

private boolean getDestination() {

    return destination;
}
Run Code Online (Sandbox Code Playgroud)

}

我的问题是,如果ArrayList::new这里不起作用,将起作用.我尝试了不同的变化,但似乎都没有

Rav*_*ala 7

只需改变它,

tracings.stream().collect(ArrayList::new, (left, right) -> left.add(right), (left, right) -> {
    left.addAll(right);
});
Run Code Online (Sandbox Code Playgroud)

你需要的是一个BiConsumer不是BinaryOperator.你上面传递的是一个BinaryOperator.

这是一个例子BinaryOperator.

BinaryOperator<List<Integer>> s = (left, right) -> {
            left.addAll(right);
            return left;
};
Run Code Online (Sandbox Code Playgroud)

作为一种优秀的工程实践,总是更喜欢lambdas的方法引用.所以这里是使用方法引用代替lambdas的增强版本.

tracings.stream().collect(ArrayList::new, List::add, List::addAll);
Run Code Online (Sandbox Code Playgroud)

  • 这基本上是`Collectors.toList()`在内部执行的操作,尽管规范提供了不同的空间(即不返回`ArrayList`而是另一个`List`实现).但是当你使用`Collectors.toCollection(ArrayList :: new)`时,你就会得到它.混淆可能源于`Collector.of(...)`,其合并函数*是一个二元运算符:`tracings.stream().collect(Collector.of(ArrayList :: new,List :: add,(l,r) ) - > {l.addAll(r); return l;})`.这允许潜在的优化,即`(l,r) - > {if(l.isEmpty())返回r; l.addAll(r) ;返回l;}` (3认同)
  • OP问*"什么会起作用"*.方法引用和lambdas一样有用.但我更愿意展示最佳实践和解释,而不仅仅是修复编译问题. (2认同)

Nam*_*man 5

你似乎在寻找:

tracings.stream()
        .collect(ArrayList::new, 
                 ArrayList::add, 
                 ArrayList::addAll);
Run Code Online (Sandbox Code Playgroud)

这与lambda表示相同:

tracings.stream()
        .collect(ArrayList::new, 
                 (left, right) -> left.add(right), 
                 (left, right) -> left.addAll(right)); // notice no 'return'
Run Code Online (Sandbox Code Playgroud)

原因:Stream.collect期望a BiConsumer作为参数,其具有返回类型的accept方法void.