美文网首页java基础
Java8函数式编程(三):Collectors.groupin

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

作者: packet | 来源:发表于2018-07-20 19:15 被阅读0次

    上周看同事代码,看到了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 例子

    相关文章

      网友评论

        本文标题:Java8函数式编程(三):Collectors.groupin

        本文链接:https://www.haomeiwen.com/subject/nrgqmftx.html