如何用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
相关产品推荐
相关产品推荐

