Java8之Stream之List转Map有哪些坑

简介: Java8之Stream之List转Map有哪些坑

Duplicate key 问题



当 key 值重复时会有这个问题,异常如下


Exception in thread "main" java.lang.IllegalStateException: Duplicate key 小C
  at java.util.stream.Collectors.lambda$throwingMerger$0(Unknown Source)
  at java.util.HashMap.merge(Unknown Source)
  at java.util.stream.Collectors.lambda$toMap$58(Unknown Source)
  at java.util.stream.ReduceOps$3ReducingSink.accept(Unknown Source)
  at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(Unknown Source)
  at java.util.stream.AbstractPipeline.copyInto(Unknown Source)
  at java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
  at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source)
  at java.util.stream.AbstractPipeline.evaluate(Unknown Source)
  at java.util.stream.ReferencePipeline.collect(Unknown Source)
  at JavaBase.lamda.List2Map.main(List2Map.java:47)

Duplicate key 解决办法一:遇到重复的key就使用后者替换


// 后面的值代替之前的值
Map<String, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName,(value1 , value2)-> value2 ));

Duplicate key 解决办法二:重复时将前面的value和后面的value拼接起来


// 重复时将前面的value 和后面的value拼接起来
Map<String, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName,(value1 , value2)-> value1+","+value2 ));

Duplicate key 解决办法三:重复时将重复key的数据组成集合

// 重复时将重复key的数据组成集合
Map<String, List<String>> map = list.stream().collect(Collectors.toMap(Person::getId, p -> {
            List<String> getNameList = new ArrayList<>();
            getNameList.add(p.getName());
            return getNameList;
        }, (List<String> value1, List<String> value2) -> {
            value1.addAll(value2);
            return value1;
        }));

NullPointerException 问题


Exception in thread "main" java.lang.NullPointerException
  at java.util.HashMap.merge(Unknown Source)
  at java.util.stream.Collectors.lambda$toMap$58(Unknown Source)
  at java.util.stream.ReduceOps$3ReducingSink.accept(Unknown Source)
  at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(Unknown Source)
  at java.util.stream.AbstractPipeline.copyInto(Unknown Source)
  at java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
  at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source)
  at java.util.stream.AbstractPipeline.evaluate(Unknown Source)
  at java.util.stream.ReferencePipeline.collect(Unknown Source)
  at JavaBase.lamda.List2Map.main(List2Map.java:47)

解决办法


Map<String, String> map = (Map<String, String>) list.stream().collect(HashMap::new,(k, v) ->k.put(v.getId(),v.getName()),HashMap::putAll);

Map类集合Key/Value能否存储null值情况表格


集合类 Key Value Super 说明
ConcurrentHashMap 不允许为null 不允许为null AbstractMap 分段锁技术
Hashtable 不允许为null 不允许为null Dictionary 线程安全
HashMap 允许为null 允许为null AbstractMap 线程不安全
TreeMap 不允许为null 允许为null AbstractMap 线程不安全

完整测试代码



import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class Person {
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    private String id;
    private String name;
    public Person(String id, String name) {
        this.id = id;
        this.name = name;
    }
}
public class List2Map {
    public static void main(String[] args) {
        // 声明一个List集合
        List<Person> list = new ArrayList();
        list.add(new Person("1001", "小A"));
        list.add(new Person("1002", "小B"));
        list.add(new Person("1003", "小C"));
//        list.add(new Person("1003", "小D"));
        list.add(new Person("1004", null));
//        list.add(new Person(null, "小D"));
        // 将list转换map
        Map<String, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName));
        // 后面的值代替之前的值
//        Map<String, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName,(value1 , value2)-> value2 ));
        // 重复时将前面的value 和后面的value拼接起来
//        Map<String, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName,(value1 , value2)-> value1+","+value2 ));
        // 重复时将重复key的数据组成集合
      /*  Map<String, List<String>> map = list.stream().collect(Collectors.toMap(Person::getId, p -> {
            List<String> getNameList = new ArrayList<>();
            getNameList.add(p.getName());
            return getNameList;
        }, (List<String> value1, List<String> value2) -> {
            value1.addAll(value2);
            return value1;
        }));*/
//        Map<String, String> map = (Map<String, String>) list.stream().collect(HashMap::new,(k, v) ->k.put(v.getId(),v.getName()),HashMap::putAll);
        System.out.println(map);
    }
}


相关文章
|
27天前
|
安全 Java 程序员
深入Java集合框架:解密List的Fail-Fast与Fail-Safe机制
本文介绍了 Java 中 List 的遍历和删除操作,重点讨论了快速失败(fail-fast)和安全失败(fail-safe)机制。通过普通 for 循环、迭代器和 foreach 循环的对比,详细解释了各种方法的优缺点及适用场景,特别是在多线程环境下的表现。最后推荐了适合高并发场景的 fail-safe 容器,如 CopyOnWriteArrayList 和 ConcurrentHashMap。
53 5
|
25天前
|
Java 程序员 编译器
Java|如何正确地在遍历 List 时删除元素
从源码分析如何正确地在遍历 List 时删除元素。为什么有的写法会导致异常,而另一些不会。
19 3
|
25天前
|
Java 程序员
Java|List.subList 踩坑小记
不应该仅凭印象和猜测,就开始使用一个方法,至少花一分钟认真读完它的官方注释文档。
21 1
|
2月前
|
Java C# Swift
Java Stream中peek和map不为人知的秘密
本文通过一个Java Stream中的示例,探讨了`peek`方法在流式处理中的应用及其潜在问题。首先介绍了`peek`的基本定义与使用,并通过代码展示了其如何在流中对每个元素进行操作而不返回结果。接着讨论了`peek`作为中间操作的懒执行特性,强调了如果没有终端操作则不会执行的问题。文章指出,在某些情况下使用`peek`可能比`map`更简洁,但也需注意其懒执行带来的影响。
140 2
Java Stream中peek和map不为人知的秘密
|
1月前
|
存储 分布式计算 Java
Stream很好,Map很酷,但答应我别用toMap():Java开发中的高效集合操作
在Java的世界里,Stream API和Map集合无疑是两大强大的工具,它们极大地简化了数据处理和集合操作的复杂度。然而,在享受这些便利的同时,我们也应当警惕一些潜在的陷阱,尤其是当Stream与Map结合使用时。本文将深入探讨Stream与Map的优雅用法,并特别指出在使用toMap()方法时需要注意的问题,旨在帮助大家在工作中更高效、更安全地使用这些技术。
42 0
|
3月前
|
Java
用JAVA架建List集合为树形结构的代码方法
这段代码定义了一个表示树形结构的 `Node` 类和一个用于构建树形结构的 `TreeController`。`Node` 类包含基本属性如 `id`、`pid`、`name` 和 `type`,以及子节点列表 `children`。`TreeController` 包含初始化节点列表并将其转换为树形结构的方法。通过过滤和分组操作实现树形结构的构建。详情可见:[代码示例链接1](http://www.zidongmutanji.com/zsjx/43551.html),[代码效果参考链接2](https://www.257342.com/sitemap/post.html)。
44 5
|
2月前
|
Java API 开发者
代码小妙招:用Java轻松获取List交集数据
在Java中获取两个 `List`的交集可以通过 `retainAll`方法和Java 8引入的流操作来实现。使用 `retainAll`方法更为直接,但会修改原始 `List`的内容。而使用流则提供了不修改原始 `List`、更为灵活的处理方式。开发者可以根据具体的需求和场景,选择最适合的方法来实现。了解和掌握这些方法,能够帮助开发者在实际开发中更高效地处理集合相关的问题。
96 1
|
2月前
|
Go 定位技术 索引
Go 语言Map(集合) | 19
Go 语言Map(集合) | 19
|
2月前
|
存储 前端开发 API
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
该文章详细介绍了ES6中Set和Map数据结构的特性和使用方法,并探讨了它们在前端开发中的具体应用,包括如何利用这些数据结构来解决常见的编程问题。
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
|
3月前
|
存储 安全 Java
java集合框架复习----(4)Map、List、set
这篇文章是Java集合框架的复习总结,重点介绍了Map集合的特点和HashMap的使用,以及Collections工具类的使用示例,同时回顾了List、Set和Map集合的概念和特点,以及Collection工具类的作用。
java集合框架复习----(4)Map、List、set