上周看同事代码,看到了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()));