You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Stream API分组List中的Item并保留原列表顺序?

解决Stream API分组并保留原列表顺序的问题

这个问题我之前也碰到过,Collectors.groupingBy默认用的是HashMap,它不保证插入顺序,所以会打乱原列表里key出现的先后顺序。不过只要换个Map实现就能轻松搞定!

第一步:将Item列表分组为List<List<Item>>

我们可以用groupingBy的重载方法,指定LinkedHashMap作为底层存储容器——它会严格保留key第一次出现的顺序,完美契合你的需求。之后把Map的values直接转成List就行:

import java.util.*;
import java.util.stream.Collectors;

class Item {
    private String key;
    private String $value;

    // 构造器、getter和setter
    public Item(String key, String $value) {
        this.key = key;
        this.$value = $value;
    }

    public String getKey() {
        return key;
    }

    public String get$value() {
        return $value;
    }

    @Override
    public String toString() {
        return "Item{" + "key='" + key + '\'' + ", $value='" + $value + '\'' + '}';
    }
}

public class Main {
    public static void main(String[] args) {
        List<Item> itemList = Arrays.asList(
                new Item("key1", "value1"),
                new Item("key2", "value2"),
                new Item("key2", "value3")
        );

        // 分组并保留原列表顺序
        List<List<Item>> groupedList = itemList.stream()
                .collect(Collectors.groupingBy(
                        Item::getKey,
                        LinkedHashMap::new, // 指定保留顺序的Map实现
                        Collectors.toList()
                ))
                .values() // 提取所有分组的列表
                .stream()
                .collect(Collectors.toList());

        // 输出验证结果
        groupedList.forEach(System.out::println);
    }
}

运行后会输出你期望的格式:

[Item{key='key1', $value='value1'}]
[Item{key='key2', $value='value2'}, Item{key='key2', $value='value3'}]

第二步:转换为List<AnotherObject>

接下来把分组结果转换成AnotherObject的列表,只需要遍历Map的entrySet,每个entry对应一个AnotherObject实例就行:

先定义AnotherObject类:

class AnotherObject {
    private String key;
    private List<Item> $items;

    // 构造器、getter和setter
    public AnotherObject(String key, List<Item> $items) {
        this.key = key;
        this.$items = $items;
    }

    public String getKey() {
        return key;
    }

    public List<Item> get$items() {
        return $items;
    }

    @Override
    public String toString() {
        return "AnotherObject{" + "key='" + key + '\'' + ", $items=" + $items + '}';
    }
}

然后修改主方法里的转换逻辑:

List<AnotherObject> anotherObjectList = itemList.stream()
        .collect(Collectors.groupingBy(
                Item::getKey,
                LinkedHashMap::new,
                Collectors.toList()
        ))
        .entrySet()
        .stream()
        .map(entry -> new AnotherObject(entry.getKey(), entry.getValue()))
        .collect(Collectors.toList());

// 输出验证结果
anotherObjectList.forEach(System.out::println);

运行后会得到你想要的最终格式:

AnotherObject{key='key1', $items=[Item{key='key1', $value='value1'}]}
AnotherObject{key='key2', $items=[Item{key='key2', $value='value2'}, Item{key='key2', $value='value3'}]}

关键说明

  • LinkedHashMap是核心:它会按照key第一次被插入的顺序存储条目,完美匹配保留原列表顺序的需求。
  • 这段代码兼容Java 8及以上版本;如果是Java 16+,还可以用Collectors.toList()返回的不可变列表,核心逻辑不受影响。

内容的提问来源于stack exchange,提问作者Flerex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:39:12