Java8 Stream 对List根据一个或多个字段分组

转载:https://blog.csdn.net/y1h2l/article/details/105335072

  • 写在前面的
  • 正文
    • java8 新特性Stresm API
    • 根据一个字段进行分组
    • 根据多个字段进行分组
  • 总结
     

写在前面的

项目中遇到了需要对list进行分组的场景,根据List中entity的某字段或者多个字段进行分组,形成Map,然后根据map进行相关的业务操作。

之前考虑自己遍历list进行处理,总感觉还有更便捷的方法,分享下。。

正文

java8 新特性Stream API

Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行比较复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

下边实现的list分组代码就使用了Stream Api。

根据一个字段进行分组

import cn.hutool.json.JSONUtil;
import com.test.collection.entity.Score;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 对list进行分组
 *
 * @ClassName: ListGroupBy
 * @Author: myx
 * @Date: 2020/4/5 20:22
 **/
public class ListGroupBy {
    public static void main(String[] args) {
        List scoreList = new ArrayList<>();
        scoreList.add(new Score().setStudentId("001").setScoreYear("2018").setScore(100.0));
        scoreList.add(new Score().setStudentId("001").setScoreYear("2019").setScore(59.5));
        scoreList.add(new Score().setStudentId("001").setScoreYear("2019").setScore(99.0));
        scoreList.add(new Score().setStudentId("002").setScoreYear("2018").setScore(99.6));
        //根据scoreYear字段进行分组
        Map> map = scoreList.stream().collect(
                Collectors.groupingBy(
                        score -> score.getScoreYear()
                ));
        System.out.println(JSONUtil.toJsonPrettyStr(map));
    }
}

输出结果如下:

{
    "2019": [
        {
            "studentId": "001",
            "score": 59.5,
            "scoreYear": "2019"
        },
        {
            "studentId": "001",
            "score": 99,
            "scoreYear": "2019"
        }
    ],
    "2018": [
        {
            "studentId": "001",
            "score": 100,
            "scoreYear": "2018"
        },
        {
            "studentId": "002",
            "score": 99.6,
            "scoreYear": "2018"
        }
    ]
}

根据多个字段进行分组

将上述代码中

//根据scoreYear字段进行分组
Map> map = scoreList.stream().collect(
    Collectors.groupingBy(
        score -> score.getScoreYear()
    ));

修改成:

//根据scoreYear和studentId字段进行分组
        Map> map = scoreList.stream().collect(
                Collectors.groupingBy(
                        score -> score.getScoreYear()+'-'+score.getStudentId()
                ));

输出结果如下:

{
    "2019-001": [
        {
            "studentId": "001",
            "score": 59.5,
            "scoreYear": "2019"
        },
        {
            "studentId": "001",
            "score": 99,
            "scoreYear": "2019"
        }
    ],
    "2018-001": [
        {
            "studentId": "001",
            "score": 100,
            "scoreYear": "2018"
        }
    ],
    "2018-002": [
        {
            "studentId": "002",
            "score": 99.6,
            "scoreYear": "2018"
        }
    ]
}

总结

  1. 本文提到的list分组方式适用于Java 8版本,低版本的不支持
  2. 对于list多字段的分组操作,groupingBy内传入的是多个字段拼接起来的一个复合字段,分组后形成map的key,就是拼接后的复合字段

你可能感兴趣的:(java,java)