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

如何将Stream<Person>分组为Stream<List<Person>>而非Map<String,List<Person>>

问题解答

方案1:基于现有分组逻辑快速实现(底层用Map,无需显式维护Map变量)

该方案实现最简单、性能稳定,时间复杂度为O(n),是绝大多数场景的最优选择。底层虽然用Map做分组,但你不需要手动维护Map实例,也不需要处理分组key,完全满足「不需要保留分组key」的需求:

Stream<List<Person>> resultStream = persons.stream()
        .collect(Collectors.groupingBy(Person::getName))
        .values()
        .stream();

方案2:完全不使用Map实现(需保证同name元素连续)

如果要求全程不使用Map集合,可以实现,但需要满足「相同name的Person元素在列表中连续排列」的前提:

  • 如果原始列表没有这个特性,需要先按name属性排序,会引入O(nlogn)的排序性能开销
  • 如果原始列表已经保证同name元素连续,可以直接跳过排序步骤,时间复杂度为O(n)

JDK原生实现示例:

// 1. 先按name排序(原始列表已满足同name连续可删除此步骤)
List<Person> sortedPersons = persons.stream()
        .sorted(Comparator.comparing(Person::getName))
        .toList();

// 2. 拆分连续同name的元素为独立列表
Stream<List<Person>> resultStream = Stream.iterate(0, i -> i < sortedPersons.size(), i -> {
    String currentName = sortedPersons.get(i).getName();
    int end = i;
    while (end < sortedPersons.size() && sortedPersons.get(end).getName().equals(currentName)) end++;
    return end;
}).map(i -> {
    String currentName = sortedPersons.get(i).getName();
    int end = i;
    while (end < sortedPersons.size() && sortedPersons.get(end).getName().equals(currentName)) end++;
    return sortedPersons.subList(i, end);
});

你也可以通过自定义Collector实现更优雅的连续分组逻辑,避免重复遍历判断下标。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 03:36:04