Java8函数式编程(三):Collectors.groupingBy

上周看同事代码,看到了Collectors.groupingBy的一些使用,由于时间限制,不允许做太多学习,所以周末研究一下。

先祭出VO:

@Getter
@Setter
@ToString
class Fruit {
    private String name;
    private Double price;

    public Fruit(String name, Double price) {
        this.name = name;
        this.price = price;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Fruit fruit = (Fruit) o;
        return java.util.Objects.equals(name, fruit.name) &&
                java.util.Objects.equals(price, fruit.price);
    }

    @Override
    public int hashCode() {
        return java.util.Objects.hash(name, price);
    }
    // 注意equals和hashCode必须成对出现
}

1)计数

List fruitList = Lists.newArrayList(new Fruit("apple", 6),
        new Fruit("apple", 6),
        new Fruit("banana", 7), new Fruit("banana", 7),
        new Fruit("banana", 7), new Fruit("grape",8));

Map map = fruitList.stream().
   collect(Collectors.groupingBy(Fruit::getName,Collectors.counting()));

输出结果是:{banana=3, apple=2, grape=1}
换一种啰嗦、复杂的写法,但能加深理解。

Map map = fruitList.stream().map(Fruit::getName).
  collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

2)排序
现在要按照水果map中value的数量逆序打印每个entry

map.entrySet().stream().sorted(Map.Entry.comparingByValue().reversed())
         .forEachOrdered(System.out::println);

3)累加求和

Map sumMap = fruitList.stream().collect.
(Collectors.groupingBy(Fruit::getName, Collectors.summingInt(Fruit::getPrice)));

输出结果是:{banana=21, apple=12, grape=8}
4)分组

Map> groupMap = 
fruitList.stream().collect(Collectors.groupingBy(Fruit::getName));

上述代码根据name将list分组,如果name是唯一的,那么上述代码就会显得啰嗦。我们需要知道,Guava补JDK之不足,现在改Guava一显身手了。

Map map = Maps.uniqueIndex(fruitList, Fruit::getName);

生成的Map是ImmutableMap,不可更改里面的值。比如map.remove("apple")会抛出异常:java.lang.UnsupportedOperationException

根据不同的名字分为若干组

// group by price, uses 'mapping' to convert List to List
Map> groupMap = 
fruitList.stream().collect(Collectors.groupingBy(Fruit::getName, 
Collectors.mapping(Fruit::getPrice, Collectors.toList())));

上面一段代码可以用Guava代替

Multimap multiMap = ArrayListMultimap.create();
fruitList.forEach(fruit -> multiMap.put(fruit.getName(), fruit.getPrice()));

鸣谢:Stream Collectors groupingBy 例子

你可能感兴趣的:(Java8函数式编程(三):Collectors.groupingBy)