将常规循环转换为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<Product> 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;
}