Lambda 使用Java8流对列表项进行分组和求和
假设我有一个Lambda 使用Java8流对列表项进行分组和求和,lambda,collections,java-8,java-stream,Lambda,Collections,Java 8,Java Stream,假设我有一个列表。其中香蕉类定义如下: Banana.java public class Banana{ String name; Long weight; Long price; // getters & setters } 香蕉列表包含: [ {"banana1", 10, 20}, {"banana1", 10, 20}, {"banana1", 10, 20}, {"banana2", 20, 30}, {"banana
列表
。其中香蕉类定义如下:
Banana.java
public class Banana{
String name;
Long weight;
Long price;
// getters & setters
}
香蕉列表包含:
[
{"banana1", 10, 20},
{"banana1", 10, 20},
{"banana1", 10, 20},
{"banana2", 20, 30},
{"banana2", 30, 30},
{"banana3", 50, 40},
]
我想在这里做的是按香蕉的名字分组,在其中求和权重列和价格列(每个单独),这样我可以得到以下结果:
[
{"banana1", 30, 60},
{"banana2", 50, 60},
{"banana3", 50, 40},
]
提前感谢。您可以使用合并功能将它们与
收集器分组。toMap
:
Map<String,Banana> bananasByName =
bananas.stream()
.collect(Collectors.toMap(Banana::getName,
Function.identity(),
(b1,b2)->{
b1.addWeightAndPrice(b2); return b1;
}));
Map bananasByName=
香蕉流
.collect(收集器).toMap(香蕉::getName,
Function.identity(),
(b1,b2)->{
b1.添加权重和价格(b2);返回b1;
}));
其中,addweightnandprice
是Banana
类的一个实例方法,它将传递的Banana
的权重和价格添加到调用它的Banana
实例中
如果您不想改变原始的Banana
实例,您可以更改merge函数来创建一个新的Banana
实例,并将两个输入Banana
实例的权重和价格添加到该实例中。下面的答案,以及通过以下途径测试的完整实现:
另一种解决方案与此类似: 我将解决方案简化为三个步骤。由于为它定义了
BiFunction
和Function
第一个功能
此BiFunction
获取两个香蕉对象并返回一个求和期望属性的香蕉对象。(价格、重量)
双功能=
(o1,o2)->新香蕉(o2.getName(),o1.getWeight()+o2.getWeight(),
o1.getPrice()+o2.getPrice());
和第二功能
List<Banana> bananaList = bananas.stream()
.collect(Collectors.groupingBy(Banana::getName)).values()
.stream()
.map(function2::apply)
.collect(Collectors.toList());
此函数用于获取香蕉对象列表并返回单个香蕉
Function<List<Banana>, Banana> function2 =
l -> l.stream()
.reduce(new Banana("",0l,0l),(o1, o2) -> function.apply(o1, o2));
功能2=
l->l.流()
.减少(新香蕉(“,0l,0l),(o1,o2)->功能。应用(o1,o2));
最后
List<Banana> bananaList = bananas.stream()
.collect(Collectors.groupingBy(Banana::getName)).values()
.stream()
.map(function2::apply)
.collect(Collectors.toList());
List bananaList=bananaList.stream()
.collect(Collectors.groupingBy(Banana::getName)).values()
.stream()
.map(函数2::应用)
.collect(Collectors.toList());
List bananaList=bananaList.stream()
.collect(Collectors.groupingBy(Banana::getName)).values()
.stream()
.map(巴拿大人1->巴拿大人1
.stream()
.减少(新香蕉(“、0升、0升),
(banana1,banana2)->新香蕉(banana2.getName(),
banana1.getWeight()+banana2.getWeight(),
banana1.getPrice()+banana2.getPrice())
.collect(Collectors.toList());
感谢您提供的示例,我本想对您的回答投赞成票,但不幸的是,我不能:(好吧,希望其他一些慷慨的SO用户也会这么做。Regardsless-我希望这个答案能帮助你,伙计。虽然StringJoiner
是一个有用的工具,但与简单的return name+”、“+weight+”、”相比,它在这里的使用并不令人信服。”+price;
@Holger:这不是主要问题,但感谢您的投入。
Function<List<Banana>, Banana> function2 =
l -> l.stream()
.reduce(new Banana("",0l,0l),(o1, o2) -> function.apply(o1, o2));
List<Banana> bananaList = bananas.stream()
.collect(Collectors.groupingBy(Banana::getName)).values()
.stream()
.map(function2::apply)
.collect(Collectors.toList());
List<Banana> bananaList = bananas.stream()
.collect(Collectors.groupingBy(Banana::getName)).values()
.stream()
.map(bananas1 -> bananas1
.stream()
.reduce(new Banana("",0l,0l),
(banana1,banana2)->new Banana(banana2.getName(),
banana1.getWeight() + banana2.getWeight(),
banana1.getPrice() + banana2.getPrice())))
.collect(Collectors.toList());