Stream系列之集合分组

Lin2J
2021-04-01 / 0 评论 / 191 阅读
温馨提示:
本文最后更新于2021-04-01,若内容或图片失效,请留言反馈。

示例源码

辅助类

@Data
@AllArgsConstructor
public class User {
    private String name;
    private Integer age;
}

groupingBy() -- 分组

Java8 中的 groupingBy 实现集合的分组,类似于 Mysql 中的 group by 操作,返回一个 Map

package com.jia.blogdemo.stream;

/**
 * @author linjinjia linjinjia047@163.com
 * @date 2021/4/1 18:10
 */
public class GroupByDemo {

    public static void main(String[] args) {
        List<User> users = new ArrayList<>();
        users.add(new User("a", 12));
        users.add(new User("a", 14));
        users.add(new User("a", 12));
        users.add(new User("b", 12));
        users.add(new User("b", 12));
        users.add(new User("b", 14));
        // 对集合的元素按照某一个字段进行分组
        groupByOnField(users);
        // 对集合的多个字段同时作为分组条件
        groupByMultiField1(users);
        // 对集合的多个字段先后进行分组
        groupByMultiField2(users);
    }
}
场景一:只对一个字段进行分组
private static void groupByOnField(List<User> users) {
    Map<String, List<User>> map =
        users.stream().collect(Collectors.groupingBy(User::getName));
    System.out.println(map);
}

输出:

{a=[User(name=a, age=12), User(name=a, age=14), User(name=a, age=12)], b=[User(name=b, age=12), User(name=b, age=12), User(name=b, age=14)]}

debug 截图

group-by-one-field

场景二:两个字段结合起来,作为分组条件
private static void groupByMultiField1(List<User> users) {
    Map<String, List<User>> map =
        users.stream().collect(Collectors.groupingBy(GroupByDemo::groupString));
    System.out.println(map);
}
private static String groupString(User user) {
    return user.getName() + user.getAge();
}

输出:

{b12=[User(name=b, age=12), User(name=b, age=12)], a12=[User(name=a, age=12), User(name=a, age=12)], b14=[User(name=b, age=14)], a14=[User(name=a, age=14)]}
场景三:先对某一个字段分组,然后再将各组内的元素按照另一个字段分组
private static void groupByMultiField2(List<User> users) {
    Map<String, Map<Integer, List<User>>> map =
        users.stream().collect(Collectors.groupingBy(User::getName, Collectors.groupingBy(User::getAge)));
    System.out.println(map);
    System.out.println(map.get("a").get(12).get(0));
}

输出:

{a={12=[User(name=a, age=12), User(name=a, age=12)], 14=[User(name=a, age=14)]}, b={12=[User(name=b, age=12), User(name=b, age=12)], 14=[User(name=b, age=14)]}}
User(name=a, age=12)

debug 截图

group-by-multi-field

partitioningBy() -- 分区

partitioningBy() 是根据断言,然后将集合分为两部分,truefalse,操作返回 Map

package com.jia.blogdemo.stream;

/**
 * @author linjinjia linjinjia047@163.com
 * @date 2021/4/1 22:08
 */
public class PartitioningByDemo {

    public static void main(String[] args) {
        List<User> users = new ArrayList<>();
        users.add(new User("a", 12));
        users.add(new User("b", 13));
        users.add(new User("c", 14));
        users.add(new User("e", 15));
        users.add(new User("f", 16));
        users.add(new User("g", 17));

        partitioningByOneField(users);
        partitioningAndCount(users);
    }

    /**
     * 场景一:为某个字段设置断言,分为两个组合
     */
    private static void partitioningByOneField(List<User> user) {
        Map<Boolean, List<User>> map =
                user.stream().collect(Collectors.partitioningBy(u -> u.getAge() > 15));
        System.out.println(map);
    }

    /**
     * 场景二:为某个字段设置断言,分为两个组合,然后统计两个组合的元素个数
     */
    private static void partitioningAndCount(List<User> users) {
        Map<Boolean, Long> map =
                users.stream().collect(Collectors.partitioningBy(u -> u.getAge() > 15, Collectors.counting()));
        System.out.println(map);
    }
}
场景一:为某个字段设置断言,分为两个组合
private static void partitioningByOneField(List<User> user) {
    Map<Boolean, List<User>> map =
        user.stream().collect(Collectors.partitioningBy(u -> u.getAge() > 15));
    System.out.println(map);
}

输出:

{false=[User(name=a, age=12), User(name=b, age=13), User(name=c, age=14), User(name=e, age=15)], true=[User(name=f, age=16), User(name=g, age=17)]}
场景二:为某个字段设置断言,分为两个组合,然后统计两个组合的元素个数
private static void partitioningAndCount(List<User> users) {
    Map<Boolean, Long> map =
        users.stream().collect(Collectors.partitioningBy(u -> u.getAge() > 15, Collectors.counting()));
    System.out.println(map);
}

输出:

{false=4, true=2}