Java Stream流 List< T >转换Map方法汇总合集(大概是最全吧)

Java Stream流 List< T >转换Map方法汇总合集(大概是最全吧)

本文主要介绍 Java 中利用 Stream 流将 List< T > 类型数据转换成 Map 类型的几种方法整合汇总,其中包含了toMap()、groupingBy()、partitioningBy()等方法的使用,建议收藏方便查阅,如果有帮助到您,不要吝啬点赞、收藏!

tips:本文没有推荐使用三方类库提供的 List 转 Map 工具类方法,因为在博主公司引入三方依赖需要在评审时说出引用原因,哈哈哈(太麻烦),当然有很多好用三方工具类可以直接完成 List 转 Map 的操作,如有需要,后续博主会单独写一篇三方类库的 List 转 Map 工具类方法博文提供给大家。

💗💗💗您的点赞、收藏、评论是博主输出优质文章的的动力!!!💗💗💗

以下示例会覆盖工作中绝大部分的使用场景,如有没有覆盖到的场景,后续会基于本文持续更新!!所以大家一定要收藏!点赞!欢迎在评论区与博主沟通交流!!👇🏻 👇🏻 👇🏻

List< String > -> Map< String,List< String>>

示例一

通过Stream流完成转换:

 	@Test
    public void testList1() {
        List<String> list = Arrays.asList("s1:01", "s2:02", "s3:03", "s4:04");
        Pattern DELIMITER = Pattern.compile(":");
        Map<String, List<String>> map = list.stream().map(DELIMITER::split)
                .collect(Collectors.groupingBy(a -> a[0],
                        Collectors.mapping(a -> a[1], Collectors.toList())));
        System.out.println(JSONObject.toJSONString(map));
    }

运行结果:
在这里插入图片描述

示例二

通过forEach循环转换:

    @Test
    public void testList1() {
        List<String> list = Arrays.asList("s1:01", "s2:02", "s3:03", "s4:04");
        Map<String, Set<String>> map = new HashMap<>();
        list.forEach(location -> {
            String[] strArr = location.split(":");
            map.compute(strArr[0], (country, codes) -> {
                codes = codes == null ? new HashSet<>() : codes;
                codes.add(strArr[1]);
                return codes;
            });
        });
        System.out.println(JSONObject.toJSONString(map));
    }

运行结果:

在这里插入图片描述

List< T > -> Map< T, T >

List< Integer> -> Map< Integer,Integer>

代码示例(本示例是存在重复key,并且会以首个出现的 key 去覆盖后面出现的冲突 key):

 	@Test
    public void testList2() {
        List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 4, 5, 6, 7, 8);
        Map<Integer, Integer> collect = list.stream().collect(Collectors.toMap(k -> k, v -> v, (k1, k2) -> k1));
        System.out.println("collect:" + collect);
    }

toMap()无重复key

示例一

List泛型为 Student 对象,示例需要将name属性作为 key,age 属性作为value;

    @Test
    public void testList2() {
        List<Student> list = Lists.newArrayList(
                new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
        Map<String, Integer> collect = list.stream().collect(Collectors.toMap(Student::getName, Student::getAge));
        System.out.println(JSONObject.toJSONString(collect));
    }
示例二

List泛型为 Student 对象,示例需要将name属性作为 key, Student 对象作为value;

@Test
    public void testList2() {
        List<Student> list = Lists.newArrayList(
                new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
        Map<String, Student> collect = list.stream().collect(Collectors.toMap(Student::getName, student -> student));
        System.out.println(JSONObject.toJSONString(collect));
    }

运行结果:

在这里插入图片描述

toMap()有重复key

当存在重复 key 时,编译器会报错:java.lang.IllegalStateException: Duplicate key xxxx;
在这里插入图片描述

出现这种情况就需要在 toMap() 方法中指定 key 来避免冲突;

示例一

解决办法:使用第一个key 覆盖第二个key;

    @Test
    public void testList2() {
        List<Student> list = Lists.newArrayList(
                new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 2),
                new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
        Map<String, Student> collect = list.stream().collect(Collectors.toMap(Student::getName, student -> student, (key1, key2) -> key1));
        System.out.println(JSONObject.toJSONString(collect));
    }

运行结果(保留了 “num”:11 的对象):

在这里插入图片描述

示例二

解决办法:使用第二个key 覆盖第一个key;

	@Test
    public void testList2() {
        List<Student> list = Lists.newArrayList(
                new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 2),
                new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
        Map<String, Student> collect = list.stream().collect(Collectors.toMap(Student::getName, student -> student, (key1, key2) -> key2));
        System.out.println(JSONObject.toJSONString(collect));
    }

运行结果(保留了 “num”:2 的对象):

在这里插入图片描述

toMap()空指针异常

当 value 为空时,使用 toMap() 方法进行转换,编译器会抛出 java.lang.NullPointerException;

	@Test
    public void testList2() {
        List<Student> list = Lists.newArrayList(
                new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29),
                new Student("小田", null, DateUtil.parse("2007-02-21 22:18:56"), null));
        Map<String, Integer> collect = list.stream().collect(Collectors.toMap(Student::getName, Student::getAge));
        System.out.println(JSONObject.toJSONString(collect));
    }

运行结果:

在这里插入图片描述

解决办法一

转换时增加判断,如果是null,则设置默认值;

	@Test
    public void testList2() {
        List<Student> list = Lists.newArrayList(
                new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29),
                new Student("小田", null, DateUtil.parse("2007-02-21 22:18:56"), null));
        Map<String, Integer> collect = list.stream().collect(Collectors.toMap(Student::getName, s -> s.getAge() == null ? -1 : s.getAge()));
        System.out.println(JSONObject.toJSONString(collect));
    }

运行结果:

在这里插入图片描述

解决办法二

使用 Optional< T > 对值进行包装(和方式一大同小异,就是换了个写法):

	@Test
    public void testList2() {
        List<Student> list = Lists.newArrayList(
                new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29),
                new Student("小田", null, DateUtil.parse("2007-02-21 22:18:56"), null));
        Map<String, Integer> collect = list.stream().collect(Collectors.toMap(Student::getName,  s -> Optional.ofNullable(s.getAge()).orElse(-1)));
        System.out.println("Optional:"+JSONObject.toJSONString(collect));
    }

运行结果:

在这里插入图片描述

解决办法三

使用collect(Supplier< R > supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) 来构建,可允许null值的出现:

	@Test
    public void testList2() {
        List<Student> list = Lists.newArrayList(
                new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29),
                new Student(null, 12, DateUtil.parse("2007-02-21 22:18:56"), null));
        HashMap<Integer, String> collect = list.stream().collect(HashMap::new, (obj, v) -> obj.put(v.getAge(), v.getName()), HashMap::putAll);
        System.out.println("collect:" + collect);
    }

运行结果:

在这里插入图片描述

List< T > -> Map< T, List< T > >

groupingBy()

直接根据一个字段或者属性分组也可以直接用 groupingBy() 方法:

	@Test
    public void testList2() {
        List<Student> list = Lists.newArrayList(
                new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 2),
                new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
        Map<String, List<Student>> collect = list.stream().collect(Collectors.groupingBy(Student::getName));
        System.out.println(JSONObject.toJSONString(collect));
    }

运行结果:

在这里插入图片描述

partitioningBy()

partitioningBy() 可以理解为特殊的 groupingBy() ,key 值为 Boolean类型:

	@Test
    public void testList2() {
        List<Student> list = Lists.newArrayList(
                new Student("小张", 17, DateUtil.parse("2006-10-03 15:18:56"), 11),
                new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 5),
                new Student("小李", 15, DateUtil.parse("2008-03-19 02:18:56"), 2),
                new Student("小王", 16, DateUtil.parse("2007-02-21 22:18:56"), 29));
        Map<Boolean, List<Student>> collect = list.stream().collect(Collectors.partitioningBy(s -> s.getNum() >= 5));
        System.out.println(JSONObject.toJSONString(collect));
    }

运行结果:

在这里插入图片描述


感 谢 各 位 大 佬 的 阅 读,随 手 点 赞,日 薪 过 万~! !!
<think>好的,用户想将JSONObject转换List<Map>类型的数据结构,用Java实现。首先,我需要回忆一下相关的JSON处理库,比如Jackson或者Fastjson,但用户提供的引用中提到了JSONArray的操作,可能他们正在使用某个特定的库,比如org.json或者阿里巴巴的Fastjson? 引用[1]提到JAVA对象、ListMap和JSON之间的转换,特别是JSONArray的操作汇总,包括排序、筛选和分组。这可能涉及到将JSON结构解析为Java集合。引用[2]中的例子是StringJsonObject再List<Map<String, Object>>,这可能使用了类似JSON.parseObject的方法,但用户现在需要处理的是JSONObject到List<Map>的转换。 首先,需要明确JSONObject的结构。假设用户的JSONObject是一个包含多个键值对的对象,或者可能是一个嵌套的结构。例如,如果JSONObject的结构是一个包含多个对象的数组,那么可能需要先将其转换为JSONArray,然后再逐个解析为Map。 比如,如果JSONObject的结构类似于: { "data": [ {"key1": "value1", "key2": "value2"}, {"key3": "value3", "key4": "value4"} ] } 那么需要先获取"data"对应的JSONArray,然后遍历每个元素,将其转换Map。 根据引用[2],用户可能需要先将整个JSON字符串转换为JsonObject,然后提取对应的数组部分。例如,使用Fastjson的话,可能是这样的步骤: 1. 将JSON字符串解析为JSONObject。 2. 从JSONObject中获取JSONArray。 3. 遍历JSONArray,将每个元素转换Map。 但用户的问题直接是将JSONObject转换List<Map>,可能需要考虑JSONObject内部的结构是否是一个数组,或者每个键对应的值是一个Map。比如,如果JSONObject的结构是多个键,每个键对应一个对象,那么可能需要将这些对象收集到List中。 例如,如果JSONObject是: { "1": {"name": "Alice", "age": 30}, "2": {"name": "Bob", "age": 25} } 这时候,可能需要遍历JSONObject的所有键,将每个键对应的值(也是一个JSONObject)转换Map,然后添加到List中。 在这种情况下,代码可能是这样的(使用Fastjson): JSONObject jsonObject = ...; // 假设已经有一个JSONObject对象 List<Map<String, Object>> list = new ArrayList<>(); for (String key : jsonObject.keySet()) { JSONObject item = jsonObject.getJSONObject(key); Map<String, Object> map = item.toJavaObject(Map.class); list.add(map); } 不过,用户提供的引用中没有直接提到这种方法。引用[3]展示了使用处理来扁平化集合,可能涉及到复杂的结构转换,但用户的情况可能更简单。引用[4]提到了List覆盖的问题,需要注意在转换过程中避免重复使用同一个Map对象,导致数据覆盖。 另外,如果JSONObject本身代表的是一个数组,比如在顶层就是数组形式,但被包装成了JSONObject,可能需要检查结构是否正确。例如,如果JSON结构不正确,可能需要先调整解析方式。 可能的步骤总结: 1. 确定JSONObject的结构,是否包含一个数组字段,或者本身就是多个键值对,每个值是一个对象。 2. 使用对应的JSON库(如Fastjson)提取数组或遍历键值对。 3. 将每个JSONObject转换Map,并添加到List中。 需要检查用户使用的JSON库,假设是Fastjson,可以使用JSON.parseObject方法,或者getJSONArray来获取数组部分。例如: 如果JSON结构是数组形式: String jsonStr = "[{\"key\":\"value\"}, ...]"; JSONArray jsonArray = JSON.parseArray(jsonStr); List<Map> list = jsonArray.stream() .map(obj -> (JSONObject) obj) .map(jsonObj -> jsonObj.toJavaObject(Map.class)) .collect(Collectors.toList()); 但用户的目标是转换JSONObject,所以可能需要先从JSONObject中提取数组。例如: JSONObject jsonObject = JSON.parseObject(jsonStr); JSONArray jsonArray = jsonObject.getJSONArray("data"); 然后转换jsonArray到List<Map>。 或者,如果JSONObject的每个属性都是一个对象,那么遍历所有键,收集对应的值。 另外,需要注意类型安全,可能需要指定具体的Map类型,比如Map<String, Object>。 综上,根据用户提供的引用和问题,可能的解决方案是使用Fastjson库,先获取JSONArray,然后转换List<Map>。或者遍历JSONObject的键,将每个值转换Map。具体代码需要根据JSON结构来调整。</think>要将 $JSONObject$ 转换为 $List<Map>$ 数据结构,可以通过以下步骤实现: --- ### 步骤说明 1. **确认 $JSONObject$ 结构** 假设 $JSONObject$ 包含一个数组字段(如 `"data"`),其值为多个键值对组成的对象数组。例如: ```json { "data": [ {"name": "Alice", "age": 30}, {"name": "Bob", "age": 25} ] } ``` 2. **提取 $JSONArray$** 使用 $JSONObject.getJSONArray()$ 方法获取目标数组字段: ```java JSONObject jsonObject = JSON.parseObject(jsonString); // 解析原始JSON字符串 JSONArray jsonArray = jsonObject.getJSONArray("data"); // 提取数组字段 ``` 3. **转换为 $List<Map>$** 遍历 $JSONArray$,将每个元素转换为 $Map$ 并存入 $List$: ```java List<Map<String, Object>> resultList = new ArrayList<>(); for (int i = 0; i < jsonArray.size(); i++) { JSONObject item = jsonArray.getJSONObject(i); Map<String, Object> map = item.toJavaObject(Map.class); // 转换Map resultList.add(map); } ``` --- ### 完整代码示例 ```java import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import java.util.ArrayList; import java.util.List; import java.util.Map; public class JsonConversion { public static void main(String[] args) { String jsonString = "{\"data\":[{\"name\":\"Alice\",\"age\":30},{\"name\":\"Bob\",\"age\":25}]}"; // 1. 解析JSON字符串为JSONObject JSONObject jsonObject = JSON.parseObject(jsonString); // 2. 提取JSONArray JSONArray jsonArray = jsonObject.getJSONArray("data"); // 3. 转换List<Map> List<Map<String, Object>> resultList = new ArrayList<>(); for (int i = 0; i < jsonArray.size(); i++) { JSONObject item = jsonArray.getJSONObject(i); Map<String, Object> map = item.toJavaObject(Map.class); resultList.add(map); } System.out.println(resultList); // 输出结果 } } ``` --- ### 关键点说明 - **类型安全**:通过 `item.toJavaObject(Map.class)` 确保转换后的 $Map$ 保留键值对的原始类型[^2]。 - **空值处理**:若字段可能缺失,需添加 `if (jsonObject.containsKey("data"))` 等判断逻辑[^4]。 - **性能优化**:对于大规模数据,可结合式处理(如 `jsonArray.stream()`)提升效率[^3]。 ---
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhuzicc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值