【问题标题】:Valid Supplier for collect method of stream流的收集方法的有效供应商
【发布时间】:2019-06-05 01:24:29
【问题描述】:

我只是想创建类似于我自己的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;
}

}

我的问题是,如果 ArrayList::new 在这里不起作用,那么什么会起作用。我尝试了不同的变体,但似乎都不起作用

【问题讨论】:

    标签: java arraylist java-8 java-stream collectors


    【解决方案1】:

    就这样改吧,

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

    您需要的是BiConsumer 而不是BinaryOperator。您在上面传递的是BinaryOperator

    这是一个例子BinaryOperator

    BinaryOperator<List<Integer>> s = (left, right) -> {
                left.addAll(right);
                return left;
    };
    

    作为一种良好的工程实践,始终更喜欢方法引用而不是 lambda。因此,这是使用方法引用代替 lambda 的增强版本。

    tracings.stream().collect(ArrayList::new, List::add, List::addAll);
    

    【讨论】:

    • (left, right) -&gt; left.add(right) 可以替换为 List::add(left, right) -&gt; left.add(right) 替换为 List::addAll
    • 是的,但与问题没有直接关系。
    • OP 询问“什么会起作用”。方法引用将与 lambdas 一样工作。但我更愿意展示最佳实践和解释,而不仅仅是修复编译问题。
    • @ETO 我已根据建议更新了答案。
    • 这基本上就是 Collectors.toList() 在内部所做的,尽管规范提供了不同的空间(即不返回 ArrayList 而是另一个 List 实现)。但是,当您使用Collectors.toCollection(ArrayList::new) 时,您就会明白这一点。混淆可能源于Collector.of(…),其合并函数二元运算符:tracings.stream().collect(Collector.of(ArrayList::new, List::add, (l,r) -&gt; { l.addAll(r); return l; })。这允许潜在的优化,即(l,r) -&gt; { if(l.isEmpty()) return r; l.addAll(r); return l; }
    【解决方案2】:

    您似乎在寻找:

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

    与 lambda 表示相同:

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

    原因Stream.collect 需要 BiConsumer 作为参数,它有一个 accept 方法和 voidreturn 类型。

    【讨论】:

      【解决方案3】:

      我只是想创建有点类似于 Collectors.toList() 的 我自己的,但它似乎不起作用

      虽然其他答案指定了您做错了什么,但值得注意的是,如果您尝试创建类似于 toList() 的内容,但同时指定返回的列表类型,那么我建议使用 @987654322 @ 是专门为此目的而制作的。

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

      虽然这并不比:

      new ArrayList<>(tracings);
      

      更短更易读。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-31
        • 1970-01-01
        • 2017-07-23
        • 1970-01-01
        • 2021-09-15
        相关资源
        最近更新 更多