【问题标题】:How to convert regular for loop to java 8 streams如何将常规 for 循环转换为 java 8 流
【发布时间】:2020-06-28 02:21:38
【问题描述】:

我有课程Product 和RegionAllocation

class Product{

int id;
String region;
int price;

Product(int I'd, int price,String region){
this.id = id;
this.price = price;
this.region = region;
}
 //getters for id and price
}

List<Product> list = new ArrayList();
list.add(1, 30, "LDN")
list.add(2, 25, "NYK")

还有

class RegionAllocation{
int price;
int alloQty;

RegionAllocation(Product p)
this.price = p.getPrice();
}

RegionAllocation allocate(int a){
this.alloQty+=a;
return this;
}

}

我想使用流编写一个函数,它通过产品流式传输,并为每个产品创建 RegionAllocation 对象并根据价格值设置分配函数

List<RegionAllocation> reg = new ArrayList();
for(Product p : products) {
    RegionAllocation r = new RegionAllocation(p); 

    if(p.getRegion().equals("LDN") {
        r.allocate(0);
    } else{          
        r.allocate(p.getPrice()*5)
    }
    reg.add(r);
    }

return reg;

我想用java 8流在上面写。

【问题讨论】:

  • 你试过了吗?
  • 如果您想学习流,请查看每个元素并查看它的作用。然后一次将它们结合起来。最终,您将成为回答此类问题的人。

标签: java for-loop java-8 functional-programming java-stream


【解决方案1】:

您可以使用map 并将流收集到列表中:

List<RegionAllocation> reg = products.stream()
    .map(p -> new RegionAllocation(p).allocate(p.getRegion().equals("LDN") ? 0 : p.getPrice() * 5))
    .collect(Collectors.toList());

【讨论】:

    【解决方案2】:

    将常规循环转换为Streams 时,最好先确定每段代码的作用。

    如果我们查看您的 for 循环,我们可以推断出以下功能:

    // Creation of an empty list
    List<RegionAllocation> reg = new ArrayList();
    // Loop over the products
    for(Product p : products) {
        // Create a new RegionAllocation
        RegionAllocation r = new RegionAllocation(p); 
    
        // Allocate the RegionAllocation
        if(p.getRegion().equals("LDN") {
            r.allocate(0);
        } else{          
            r.allocate(p.getPrice()*5)
        }
        // Add the RegionAllocation to the list
        reg.add(r);
    }
    
    return reg;
    

    从这里我们已经可以看到 for 循环中的代码由两个不同的部分组成;从Product 创建和分配一个新的RegionAllocation 并将这个新的RegionAllocation 添加到列表中。

    在这种情况下,第一步是将RegionAllocation 的创建和分配提取到一个单独的方法中(我已将您的原始代码包装在一个方法中,并将其命名为createRegionAllocations)

    public List<RegionAllocation> createRegionAllocations(List<Product> products) {
        List<RegionAllocation> reg = new ArrayList();
        for(Product p : products) {
            RegionAllocation r = createRegionAllocation(p);
            reg.add(r);
        }
    
        return reg;
    }
    
    private RegionAllocation createRegionAllocation(Product p) {
        RegionAllocation r = new RegionAllocation(p); 
    
        if(p.getRegion().equals("LDN") {
            r.allocate(0);
        } else{          
            r.allocate(p.getPrice()*5)
        }
    
        return r;
    }
    

    现在我们可以将循环转换为流。循环的“for”部分

    for (Product p : products)
    

    变成

    products.stream() // Stream<Product>
    

    这是一个Stream&lt;Product&gt; aka,一个产品流。

    createRegionAllocation 方法从 Product 创建一个 RegionAllocation,因此它将一种类型 (Product) 转换为另一种类型 (RegionAllocation)。这就是map 方法对流的作用。它的签名是

    <R> Stream<R> map(Function<? super T, ? extends R> mapper)
    

    其中T 是流的类型map 被调用,R 是新类型。所以在你的情况下,我们现在可以做

    products.stream() // Stream<Product>
        .map(p -> createRegionAllocation(p)) // Stream<RegionAllocation>
    

    现在最后一步是创建流列表。这就是collect 方法的用途。收集流的方法有很多种,但对于这种情况,当我们收集时我们会这样做

    products.stream() // Stream<Product>
        .map(p -> createRegionAllocation(p)) // Stream<RegionAllocation>
        .collect(Collectors.toList()) // List<RegionAllocation>
    

    除了Collectors.toList()(收集到List)之外,您还可以执行例如Collectors.toSet()(收集到Set)或一大堆其他自定义收集器(如果需要)。但是对于Lists,你只需要记住.collect(Collectors.toList())。

    最后我们可以使用createRegionAllocation的方法引用:

    products.stream() // Stream<Product>
        .map(this::createRegionAllocation) // Stream<RegionAllocation>
        .collect(Collectors.toList()) // List<RegionAllocation>
    

    所以当我们把它们放在一起时,我们得到了

    public List<RegionAllocation> createRegionAllocations(List<Product> products) {
        return products.stream()
            .map(this::createRegionAllocation)
            .collect(Collectors.toList());
    }
    
    private RegionAllocation createRegionAllocation(Product p) {
        RegionAllocation r = new RegionAllocation(p); 
    
        if(p.getRegion().equals("LDN") {
            r.allocate(0);
        } else{          
            r.allocate(p.getPrice()*5)
        }
    
        return r;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-14
      • 2017-02-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多