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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:46:00