Java8 Stream API中实现集合list转map的多种方式

 更新时间:2025年12月10日 09:01:21   作者:codingPower  
这篇文章介绍了如何使用Java8的StreamAPI对QuotaDto对象列表进行操作,包括字段提取、映射、组装成Map、枚举类处理、元素拼接、聚合函数以及去重,文章的示例代码讲解详细,感兴趣的小伙伴可以了解下

自定义一个对象:

public class QuotaDto{
	private Long id;
	private String quotaId;
	private String quotaName;
	private String reportDate;
	private String email;
}

List<QuotaDto>  quotaDtolists = new ArrayList<>();

1. 提取对象字段集合

List<String> quotaNames = quotaDtolists.stream()
        .map(QuotaDto::getQuotaName)
        .filter(Objects::nonNull) // 过滤null值
        .collect(Collectors.toList());

优化点

使用 filter(Objects::nonNull) 避免 null 元素进入列表。

2. List转Map(唯一键)

// 方式1:对象为Value(处理重复键)
Map<String, QuotaDto> quotaMap1 = quotaDtolists.stream()
        .collect(Collectors.toMap(
            QuotaDto::getQuotaId, 
            Function.identity(),
            (v1, v2) -> v2 // 键冲突时保留新值
        ));

// 方式2:提取字段为Value
Map<String, String> quotaMap2 = quotaDtolists.stream()
        .collect(Collectors.toMap(
            QuotaDto::getQuotaId,
            QuotaDto::getQuotaName,
            (oldVal, newVal) -> newVal
        ));

关键点

必须提供合并函数 ((v1, v2) -> ...),否则重复键会抛出 IllegalStateException

3. 枚举类转Map(修正版)

public enum QuotaEnum {
    TYPE_A("A"), TYPE_B("B");

    private final String value;

    QuotaEnum(String value) { this.value = value; }
    public String getValue() { return value; } // 正确方法名

    // 枚举转Map
    private static final Map<String, QuotaEnum> VALUE_MAP = Arrays.stream(values())
            .collect(Collectors.toMap(QuotaEnum::getValue, Function.identity()));
}

修正

  • 方法名 getvaluegetValue(遵循驼峰命名)。
  • 使用 Arrays.stream() 替代 Stream.of()(更直观)。

4. List转Map(类型安全版)

List<Map<String, String>> lists = new ArrayList<>(); // 统一泛型类型
//(v1,v2)->v2 冲突解决函数,当两个不同的map对象具有相同的“userid”键值。保留第二个遇到的值V2
Map<String, String> collect = lists.stream()
        .collect(Collectors.toMap(
            map -> map.getOrDefault("userid", ""),
            map -> map.getOrDefault("orgid", ""),
            (v1, v2) -> v2
        ));

//以某个字段为key
Map<String,List<QuotaDto>> quotaMap= quotaDtolists.stream().collect(Collectors.groupingBy(QuotaDto::getQuotaName));

//list<map> 转 map
Map<String,List<Map<String,String>>> quotaMap= maps.stream().collect(Collectors.groupingBy(map->map.get("userId")));

修正

  • 统一列表中的 Map 泛型为 <String, String>,避免类型不匹配。
  • 使用 getOrDefault 防止 null 值导致的 NullPointerException

5. 元素拼接(防Null版)

String emailAddress = quotaDtolists.stream()
        .map(quota -> Optional.ofNullable(quota.getEmail())
                .map(email -> email.toUpperCase() + "@qq.com")
                .orElse("")) // 处理null或空邮件
        .filter(str -> !str.isEmpty())
        .collect(Collectors.joining(";"));
        
//简单版
String emailAddress=quotaDtolists.stream().map(Quota-Quota.getEmail().toUpperCase()+"@qq.com").collect(Collectors.joining(";"));

优化

使用 Optional 安全处理 null,并过滤空字符串。

6. 聚合操作(安全版)

List<Integer> list = Arrays.asList(1, 2, 3);
// 最大值(避免NoSuchElementException)
Integer maxValue = list.stream()
        .max(Integer::compare)
        .orElse(0); // 默认值

Integer maxValue2 = list.stream().collect(Collectors.collectingAndThen(Collectors.maxBy((a, b) -> a - b), Optional::get));

// 最小值
Integer minValue = list.stream()
        .min(Integer::compare)
        .orElse(0);
    
Integer minValue2 = list.stream().collect(Collectors.collectingAndThen(Collectors.minBy((a, b) -> a - b), Optional::get));

// 求和(直接使用sum()更高效)
int sumValue = list.stream().mapToInt(Integer::intValue).sum();

Integer sumValue2 = list.stream().collect(Collectors.summingInt(item -> item));

// 平均值
Double avg = list.stream()
        .mapToInt(Integer::intValue)
        .average()
        .orElse(0.0);

Double avg2 = list.stream().collect(Collectors.averagingDouble(x -> x));
    
// 求汇总数
long count= quotaDtolists.stream().filter(Quota-> Quota.getId()>1).collect(Collectors.counting());

优化

  • 直接使用 max()min()sum() 等终端操作,代码更简洁。
  • 避免使用复杂的 collectingAndThen,除非需要额外处理。

7. 多字段去重(可靠版)

ArrayList<QuotaDto> uniqueList = quotaDtolists.stream()
        .collect(Collectors.collectingAndThen(
            Collectors.toCollection(() -> new TreeSet<>(
                Comparator.comparing(QuotaDto::getId)
                          .thenComparing(QuotaDto::getQuotaName)
            )), 
            ArrayList::new
        ));


//方法二
ArrayList<QuotaDto> collect = quotaDtolists.stream().collect(Collectors.collectingAndThen(
            Collectors.toCollection(() -> new TreeSet<>(
                    Comparator.comparing(q -> q.getId()+";"+q.getQuotaName()))), ArrayList::new));

修正

使用 thenComparing 组合多个字段的比较,避免字符串拼接可能导致的键冲突。

最佳实践总结

  • 空值处理:始终考虑字段可能为 null 的情况,使用 filterOptional 防御。
  • 类型安全:统一集合的泛型类型,避免 ClassCastException
  • 键冲突处理:在 toMap 中始终提供合并函数,明确冲突解决策略。
  • 避免魔法字符串:如 map.get("userid") 可替换为常量,提高可维护性。
  • 优先内置方法:如 sum()average()Collectors.summingInt 更简洁。
  • 使用组合比较器:多字段去重时,避免拼接字符串,采用 thenComparing

通过遵循这些原则,可以大幅提升代码的健壮性和可读性。

到此这篇关于Java8 Stream API中实现集合list转map的多种方式的文章就介绍到这了,更多相关Java Stream list转map内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Map之computeIfAbsent使用解读

    Map之computeIfAbsent使用解读

    `computeIfAbsent`是Java 8引入的一个Map接口方法,用于简化在Map中获取值的操作,如果指定的键不存在,它会调用提供的函数生成一个新的值,并将其与键关联,这种方法减少了手动检查和插入的样板代码,使代码更加简洁和易读
    2025-02-02
  • IntelliJ IDEA中打开拼写检查与忽略提示曲线的方法

    IntelliJ IDEA中打开拼写检查与忽略提示曲线的方法

    今天小编就为大家分享一篇关于IntelliJ IDEA中打开拼写检查与忽略提示曲线的方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-10-10
  • 关于MD5算法原理与常用实现方式

    关于MD5算法原理与常用实现方式

    这篇文章主要介绍了关于MD5算法原理与常用实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • Java自动化实现PowerPoint转换为PDF

    Java自动化实现PowerPoint转换为PDF

    在日常的企业运营和个人工作中,PowerPoint(PPT/PPTX)文件因其强大的演示功能而被广泛使用,本文将详细介绍如何利用 Spire.Presentation for Java 库,通过简洁高效的代码实现 PowerPoint 到 PDF 的转换,需要的可以了解下
    2025-08-08
  • Java日期类详解(最新推荐)

    Java日期类详解(最新推荐)

    早期版本主要使用 java.util.Date、java.util.Calendar 等类,Java 8及以后引入了新的日期和时间API(JSR 310),包含在java.time包中,本文给大家介绍Java日期类的相关知识,感兴趣的朋友一起看看吧
    2025-06-06
  • java中的过滤器 Filter应用小结

    java中的过滤器 Filter应用小结

    文章主要介绍了Java Web中的过滤器(Filter)的基本概念、生命周期、配置和应用,过滤器可以拦截请求和响应,用于执行一些预处理或后处理操作,如设置编码、校验用户身份等,感兴趣的朋友一起看看吧
    2025-03-03
  • spring boot validation参数校验实例分析

    spring boot validation参数校验实例分析

    这篇文章主要介绍了spring boot validation参数校验,结合实例形式分析了spring boot validation进行数据有效性验证的相关操作技巧,需要的朋友可以参考下
    2019-11-11
  • 详解Java并发包基石AQS

    详解Java并发包基石AQS

    Java并发包(JUC)中提供了很多并发工具,这其中,很多我们耳熟能详的并发工具,譬如ReentrangLock、Semaphore,它们的实现都用到了一个共同的基类--AbstractQueuedSynchronizer,简称AQS。本文将从几个方面来详细介绍:基本实现原理、自定义同步器、源码分析
    2021-06-06
  • Java实现简易版猜灯谜游戏的示例代码

    Java实现简易版猜灯谜游戏的示例代码

    灯谜是中秋节传统的活动之一,而现代化的方式则是将其制作成一个小游戏,让用户在游戏的过程中猜灯谜,互动体验更佳,所以本文小编就用Java制作一款猜灯谜小游戏吧
    2023-09-09
  • springboot项目打包发布部署的过程及jar和war的区别

    springboot项目打包发布部署的过程及jar和war的区别

    Spring Boot使用了内嵌容器,因此它的部署方式也变得非常简单灵活,可以将Spring Boot项目打包成JAR包来独立运行,Spring Boot项目既可以生成WAR包发布,也可以生成JAR包发布,那么它们有什么区别呢
    2022-11-11

最新评论