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))
            )
    );