使用java 8流对列表项进行分组和求和

时间:2018-04-09 07:50:33

标签: lambda collections java-8 java-stream

假设我有一个 List<Banana> bananas 。 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},
]

我想在这里做的是按照香蕉的名称进行分组,其中总和权重列和&amp;价格栏(单独),以便我可以得到这个结果:

[
   {"banana1", 30, 60}, 
   {"banana2", 50, 60},
   {"banana3", 50, 40},
]

提前致谢。

3 个答案:

答案 0 :(得分:6)

您可以使用合并功能将CIRCLENAME | ALARMNAME | COUNT Delhi | Fire & Smoke | 189 Mumbai | Mains Fail | 20 UP West | Predicted_Site Down | 380 Punjab | Mains Fail | 1 Kerala | Site Down | 55 Mumbai | Shelter Temperature High | 3 Gujarat | Mains Fail | 189 Kerala | Mains Fail | 198 UP West | Site Down | 16 Punjab | Shelter Temperature High | 1 Gujarat | Shelter Temperature High | 21 Maharashtra & Goa | Site Down | 1 Kerala | Shelter Temperature High | 23 Gujarat | Fire & Smoke | 14 Kerala | Fire & Smoke | 7 Delhi | Site Down | 154 UP West | Mains Fail | 470 Haryana | Mains Fail | 19 Punjab | Predicted_Site Down | 5 Mumbai | Fire & Smoke | 1 UP West | Shelter Temperature High | 92 Mumbai | Site Down | 9 UP West | Fire & Smoke | 79 Delhi | Mains Fail | 3663 Punjab | Site Down | 12 Gujarat | Site Down | 38 Delhi | Shelter Temperature High | 266 Mumbai | Predicted_Site Down | 4 分组:

Collectors.toMap

其中Map<String,Banana> bananasByName = bananas.stream() .collect(Collectors.toMap(Banana::getName, Function.identity(), (b1,b2)->{ b1.addWeightAndPrice(b2); return b1; })); addWeightAndPrice类的实例方法,它将传递的Banana的权重和价格添加到调用它的Banana实例。< / p>

如果您不想改变原始Banana实例,可以更改合并功能以创建新的Banana实例,并为其添加两个输入的权重和价格{{ 1}}实例。

答案 1 :(得分:1)

通过Eran完成经过全面测试的the java online compiler后,{{3}}的答案:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
import java.util.Map;
import java.util.function.*;
import java.util.stream.*;
import java.util.StringJoiner;

public class Java8ForEachExample {

    public static void main(String[] args) {

        //creating sample Collection
        List<Banana> myList = new ArrayList<>();
        myList.add(new Banana("B1",5,30));
        myList.add(new Banana("B1",3,60));
        myList.add(new Banana("B2",1,30));
        myList.add(new Banana("B2",4,20));
        myList.add(new Banana("B2",7,100));
        // Eran's code here:
        Map<String,Banana> bananasByName =
        myList.stream()
           .collect(Collectors.toMap(Banana::getName,
                                     Function.identity(),
                                     (b1,b2)->{b1.addWeightAndPrice(b2); return b1;}));
        // End of Eran's code
        bananasByName.entrySet().forEach(e -> { 
           System.out.println(e.getKey() + " : " + e.getValue()); 
        });
    }

}

class Banana{
   private String name;
   public int weight;
   public int price;
   public Banana(String name, int weight, int price) {
       this.name = name;
       this.weight = weight;
       this.price = price;
   }
   public String getName() {
       return name;
   }
   public int getWeight() {
       return weight;
   }
   public int getPrice() {
       return price;
   }
   public void addWeightAndPrice(Banana other) {
       this.price +=other.getPrice();
       this.weight +=other.getWeight();
   }
   @Override
   public String toString() {
       return (new StringJoiner(", ")).add(name).add(Integer.toString(weight)).
          add(Integer.toString(price)).toString();
   }

}

输出:

B2 : B2, 12, 150
B1 : B1, 8, 90

答案 2 :(得分:0)

另一个解决方案类似于: 我通过将其分解为三步来简化解决方案。定义BiFunctionFunction

第一个功能

这个BiFunction得到两个Banana对象并返回单个Banana对象,它总结了期望的属性。(价格,重量)

 BiFunction<Banana, Banana, Banana> function =
            (o1, o2) -> new Banana(o2.getName(), o1.getWeight() +o2.getWeight(),
                                   o1.getPrice() + o2.getPrice());

和第二个功能

此函数获取Banana对象列表并返回单个Banana。

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