本文记录collect的高级用法。
依然先准备测试数据
class Item implements Comparable<Item> { public String id; public int count; public Item(String id, int count) { this.id = id; this.count = count; } @Override public int compareTo(Item o) { return count - o.count; } @Override public String toString() { return String.format("(%s, %d)", id, count); } }
Item item1 = new Item("it1", 1); Item item2 = new Item("it2", 3); Item item3 = new Item("it3", 2); Item item4 = new Item("it4", -1); List<Item> list = new ArrayList<>(); list.add(item1); list.add(item2); list.add(item3); list.add(item4);
1. 转化成其他类型的集合
例如 toSet(),toList(),也可以限定具体的类型:
Set<Item> set = list.stream().collect(Collectors.toCollection(TreeSet::new));
如果Item没有实现Comparable, refer Using streams to collect into TreeSet with custom comparator
2. 转化成一个value
例如minBy,maxBy,averagingInt等
Optional<Item> res = list.stream() .collect(Collectors.minBy( Comparator.comparingInt(item -> item.count)));
double aver = list.stream().collect(Collectors.averagingInt(item -> item.count));
对于string类型的可以通过join连接
String join = list.stream() .map(item -> item.id) .collect(Collectors.joining(",", "[", "]")); //返回[it1,it2,it3,it4]
3. 分割 -- 根据判断结果分成两组
Map<Boolean, List<Item>> map = list.stream() .collect(Collectors.partitioningBy(item -> item.count > 1)); // {false=[(it1, 1), (it4, -1)], true=[(it2, 3), (it3, 2)]}
4. 分组 -- 和SQL中的groupby类似
可以实现分割的功能,为了突出效果,可以将item2的count值设置为2,然后按照count进行分组
Map<Integer, List<Item>> map = list.stream() .collect(Collectors.groupingBy(item -> item.count)); // {-1=[(it4, -1)], 1=[(it1, 1)], 2=[(it2, 2), (it3, 2)]}
5. 组合使用
比较多的在groupingBy中使用
比如求count相同的item个数
Map<Integer, Long> countMap = list.stream() .collect(Collectors.groupingBy( item -> item.count, Collectors.counting())); // {-1=1, 1=1, 2=2}
比如按count分组,结果以字符串的形式连接
Map<Integer, String> strMap = list.stream() .collect(Collectors.groupingBy( item -> item.count, Collectors.mapping(it -> it.id, Collectors.joining(",", "[", "]")))); // {-1=[it4], 1=[it1], 2=[it2,it3]}
其实就是分组完成后,对每个list进行二次操作
关于自定义collector的话题,这边不cover了。