Stream ToMap(Collectors.groupingBy) 实践
参考链接:Stream ToMap(Collectors.groupingBy) 实践_OxygenBling的博客-CSDN博客
简介
Collectors.groupingBy
返回一个实现 group by 操作的Collector对象,用于Collection Stream流分组操作。
场景
预设情景:根据年龄为List list分组,进阶分组Person对象不重复,分组Person对象不重复+保持插入顺序。
实际应用:比如分页场景,对于一些需要先对List进行分组整合并且无法在数据库实现分页的需求,可以通过指定返回Map类型,返回有序Map+程序分页处理。
代码实践
import java.util.Objects; public class Person { private String name; private Integer age; public Person(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Person)) return false; Person person = (Person) o; return Objects.equals(getName(), person.getName()) && Objects.equals(getAge(), person.getAge()); } @Override public int hashCode() { return Objects.hash(getName(), getAge()); } } public class Main { public static void main(String[] args) { List<Person> list = Arrays.asList(new Person("Lee", 20), new Person("Jack", 18), new Person("Rose", 20), new Person("Susan", 19), new Person("Lee", 20)); // 按照年龄分组 Map<Integer, List<Person>> map0 = list.stream().collect(Collectors.groupingBy(Person::getAge)); // 按照年龄分组(无重复) Map<Integer, Set<Person>> map1 = list.stream().collect(Collectors.groupingBy(Person::getAge, Collectors.toSet())); // 按照年龄分组(无重复 + 保持插入顺序) Map<Integer, Set<Person>> map2 = list.stream().collect(Collectors.groupingBy(Person::getAge, LinkedHashMap::new, Collectors.toSet())); System.out.println(map0); System.out.println(map1); System.out.println(map2); } } ---------------------- {18=[Person{name='Jack', age=18}], 19=[Person{name='Susan', age=19}], 20=[Person{name='Lee', age=20}, Person{name='Rose', age=20}, Person{name='Lee', age=20}]} {18=[Person{name='Jack', age=18}], 19=[Person{name='Susan', age=19}], 20=[Person{name='Rose', age=20}, Person{name='Lee', age=20}]} {20=[Person{name='Rose', age=20}, Person{name='Lee', age=20}], 18=[Person{name='Jack', age=18}], 19=[Person{name='Susan', age=19}]}
代码分析
Collectors.groupingBy方法实现了方法重载,method 1/2 对于一些常用操作进行了封装。
根据不同的场景选择合适的方法:当需要指定分组value类型时,使用method 2;当需要指定返回分组Map类型时,使用method 3。
Collectors.groupingBy方法源码
// method 1 public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier) { return groupingBy(classifier, toList()); } // method 2 public static <T, K, A, D> Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream) { return groupingBy(classifier, HashMap::new, downstream); } // method 3 public static <T, K, D, A, M extends Map<K, D>> Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier, Supplier<M> mapFactory, Collector<? super T, A, D> downstream) { // 具体实现 }