Java 8 根据一个键按给定列表分组并在同一列表中收集的有效方法Java8
我有以下课程:Java 8 根据一个键按给定列表分组并在同一列表中收集的有效方法Java8,java-8,java-stream,Java 8,Java Stream,我有以下课程: class A{ String property1; String property2; Double property3; Double property4; } 因此,属性1和属性2是关键 class Key{ String property1; String property2; } 我已经有一个类似的列表如下: List<A> list=new ArrayList<>(); List List=new
class A{
String property1;
String property2;
Double property3;
Double property4;
}
因此,属性1和属性2是关键
class Key{
String property1;
String property2;
}
我已经有一个类似的列表如下:
List<A> list=new ArrayList<>();
List List=new ArrayList();
我想使用键进行分组并添加到另一个列表中,以避免列表中有多个具有相同键的项:
Function<A, Key> keyFunction= r-> Key.valueOf(r.getProperty1(), r.getProperty2());
Function-keyFunction=r->Key.valueOf(r.getProperty1(),r.getProperty2());
但是,在进行分组时,我必须取属性3和属性4的平均值之和
我需要一个有效的方法来做这件事
注意:我跳过了给定类的方法。收集到
地图
是不可避免的,因为你想分组
事情。要做到这一点,蛮力的方法是:
yourListOfA
.stream()
.collect(Collectors.groupingBy(
x -> new Key(x.getProperty1(), x.getProperty2()),
Collectors.collectingAndThen(Collectors.toList(),
list -> {
double first = list.stream().mapToDouble(A::getProperty3).sum();
// or any other default
double second = list.stream().mapToDouble(A::getProperty4).average().orElse(0D);
A a = list.get(0);
return new A(a.getProperty1(), a.getProperty2(), first, second);
})))
.values();
这可以稍微改进,例如在收集器.collecting中,然后
只迭代列表
一次,因为需要自定义收集器。写一篇没有那么复杂 试着这样做:
Map<A,List<A>> map = aList
.stream()
.collect(Collectors
.groupingBy(item->new A(item.property1,item.property2)));
List<A> result= map.entrySet().stream()
.map(list->new A(list.getValue().get(0).property1,list.getValue().get(0).property1)
.avgProperty4(list.getValue())
.sumProperty3(list.getValue()))
.collect(Collectors.toList());
结果看起来怎么样<代码>映射其中
列表
将包含两个值-属性3的总和和属性4的平均值?结果应为列表,我必须仅将结果存储在列表中。只是想确保列表中没有多个项目具有相同的键,这就是我进行此练习的原因。我不想把结果当作地图。谢谢大家,我们正在讨论如何在java-12中添加bicollector和(我认为),这在这里很合适。顺便说一句,您可以在这里接受答案
public A sumProperty3(List<A> a){
this.property3 = a.stream().mapToDouble(A::getProperty3).sum();
return this;
}
public A avgProperty4(List<A> a){
this.property4 = a.stream().mapToDouble(A::getProperty4).average().getAsDouble();
return this;
}
result = aList.stream().collect(Collectors
.groupingBy(item -> new A(item.property1, item.property2),
Collectors.collectingAndThen(Collectors.toList(), list ->
new A(list.get(0).property1, list.get(0).property1)
.avgProperty4(list).sumProperty3(list))
)
);