如何用Java 8 Stream按数组首元素分组字符串数组列表?
Java 8 Stream实现分组转换的两种方式
当然可以!Java 8的Stream API完全能搞定这个分组需求,而且比命令式循环写法更简洁优雅。下面给你两种实现方式,分别用Collector(推荐)和reduce来完成:
一、用Collectors.groupingBy(最常用、最简洁)
这是Stream API专门为分组场景设计的工具,搭配Collectors.mapping可以轻松把数组的第二个元素收集到对应键的列表里。
首先先修正一下你的列表初始化(Java标准写法):
import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class PetGrouping { public static void main(String[] args) { List<String[]> pets = Arrays.asList( new String[]{"Alice", "dog"}, new String[]{"Bob", "horse"}, new String[]{"Alice", "cat"}, new String[]{"Bob", "cat"} ); // 核心分组代码 Map<String, List<String>> petMap = pets.stream() .collect(Collectors.groupingBy( arr -> arr[0], // 按数组第一个元素作为分组键 Collectors.mapping(arr -> arr[1], Collectors.toList()) // 收集每个组的第二个元素到List )); // 验证结果 petMap.forEach((owner, petsList) -> System.out.println(owner + ": " + petsList)); } }
运行后会输出:
Alice: [dog, cat] Bob: [horse, cat]
这个写法的好处是语义清晰,一眼就能看出是“按第一个元素分组,收集第二个元素”,而且不需要手动处理空列表的创建,Collector会帮你搞定。我平时处理这种分组需求几乎都是用这个写法,省心又好维护~
二、用reduce实现(底层累积方式)
虽然reduce更适合做累积计算,但也能用来实现分组逻辑,适合你理解流的底层处理过程:
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Arrays; public class PetGroupingWithReduce { public static void main(String[] args) { List<String[]> pets = Arrays.asList( new String[]{"Alice", "dog"}, new String[]{"Bob", "horse"}, new String[]{"Alice", "cat"}, new String[]{"Bob", "cat"} ); Map<String, List<String>> petMapReduce = pets.stream() .reduce( new HashMap<>(), // 初始值:空的Map (currentMap, arr) -> { // 拿到当前主人对应的宠物列表,没有就新建一个 List<String> petList = currentMap.getOrDefault(arr[0], new ArrayList<>()); petList.add(arr[1]); currentMap.put(arr[0], petList); return currentMap; }, (map1, map2) -> { // 并行流场景下合并两个Map(串行流时这个参数不会被调用) map2.forEach((owner, petsList) -> { map1.merge(owner, petsList, (existingList, newList) -> { existingList.addAll(newList); return existingList; }); }); return map1; } ); // 验证结果 petMapReduce.forEach((owner, petsList) -> System.out.println(owner + ": " + petsList)); } }
这里的思路是:用一个HashMap作为累积容器,每次处理一个数组时,把宠物添加到对应主人的列表里;如果是并行流,还要处理两个Map的合并逻辑。不过这种写法比groupingBy繁琐很多,实际开发中除非有特殊定制需求,否则优先用第一种方式。
总结
- 日常开发优先用
Collectors.groupingBy + Collectors.mapping,代码简洁易读,是专门为分组场景优化的API。 - reduce方式适合理解Stream的累积原理,但代码冗余,不推荐用于常规分组需求。
内容的提问来源于stack exchange,提问作者Mattias
相关产品推荐
相关产品推荐

