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<Fruit> 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<String, Long> map = fruitList.stream().
   collect(Collectors.groupingBy(Fruit::getName,Collectors.counting()));

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

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

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

map.entrySet().stream().sorted(Map.Entry.<String, Long>comparingByValue().reversed())
         .forEachOrdered(System.out::println);

3)累加求和

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

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

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

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

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

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

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

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

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

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

鸣谢:Stream Collectors groupingBy 例子

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Int Double Long 设置特定的stream类型, 提高性能,增加特定的函数 无存储。stream不是一...
    patrick002阅读 1,285评论 0 0
  • 一次错误 需要,一辈子忏悔 再次犯同样错误 那就等同于犯罪 今夜,我低下头来 细思,今生的是是非非 请不要为错误寻...
    吴生善阅读 182评论 0 1
  • 1 人生或许就是如此,在某个瞬间突然顿悟,说好的坚持下去的一件事情,突然就戛然而止,又突然在某个瞬间,重拾曾经的记...
    俏俏老师阅读 314评论 5 1
  • 祝你,远而安之 张开你柔美的臂膀俘获我善良的心, 欢乐却终不敌毕业的到来。 祝我们都有梦里的明天, 你居住的城...
    渐行渐远的你阅读 278评论 0 1
  • 几乎所有人第一次听到“大黄”这个名字,都会觉得主人太不上心了。这样随便的取名和那些热络又漂亮的称呼相比,黯淡了许多...
    Zahirah009阅读 297评论 2 3