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) {
    // 具体实现
}

 

posted @ 2022-06-23 10:47  WPMA  阅读(893)  评论(0)    收藏  举报