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

如何用Java 8 Stream将含嵌套对象的对象列表转为HashMap

Java 8 Stream 实现 Fruit 到关联 Flower 列表的分组

要实现需求,首先需要修正核心实体类的实现——Fruit类必须重写equals()和hashCode()方法,因为 HashMap 的键判断依赖这两个方法,只有当两个Fruit对象的name相同时,才会被视为同一个键。同时给所有实体类添加必要的构造器和 getter 方法,否则 Stream 无法访问内部属性。

修正后的实体类

import java.util.Objects;

class FruitFlower {
    private Fruit fruit;
    private Flower flower;

    public FruitFlower(Fruit fruit, Flower flower) {
        this.fruit = fruit;
        this.flower = flower;
    }

    public Fruit getFruit() {
        return fruit;
    }

    public Flower getFlower() {
        return flower;
    }
}

class Fruit {
    private String name;

    public Fruit(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    // 基于name字段重写equals和hashCode,确保同name的Fruit视为同一键
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Fruit fruit = (Fruit) o;
        return Objects.equals(name, fruit.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }

    // 重写toString方便打印结果
    @Override
    public String toString() {
        return name;
    }
}

class Flower {
    private String name;

    public Flower(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    // 重写toString方便打印结果
    @Override
    public String toString() {
        return name;
    }
}

Stream 转换实现代码

使用Collectors.groupingBy结合Collectors.mapping完成分组和属性提取:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

public class FruitFlowerGrouping {
    public static void main(String[] args) {
        List<FruitFlower> fruitFlowers = new ArrayList<>();
        fruitFlowers.add(new FruitFlower(new Fruit("Apple"), new Flower("Rose")));
        fruitFlowers.add(new FruitFlower(new Fruit("Banana"), new Flower("Lily")));
        fruitFlowers.add(new FruitFlower(new Fruit("Apple"), new Flower("Sunflower")));
        fruitFlowers.add(new FruitFlower(new Fruit("Banana"), new Flower("Purple")));
        fruitFlowers.add(new FruitFlower(new Fruit("Banana"), new Flower("Rose")));

        // 转换为HashMap<Fruit, List<Flower>>
        HashMap<Fruit, List<Flower>> resultMap = fruitFlowers.stream()
                .collect(Collectors.groupingBy(
                        FruitFlower::getFruit,          // 分组键:每个FruitFlower的Fruit对象
                        HashMap::new,                   // 指定返回容器为HashMap
                        Collectors.mapping(FruitFlower::getFlower, Collectors.toList())  // 提取并收集Flower列表
                ));

        // 打印验证结果
        resultMap.forEach((fruit, flowers) -> {
            System.out.println(fruit + ": " + flowers);
        });
    }
}

关键说明

  1. 分组逻辑:Collectors.groupingBy(FruitFlower::getFruit) 指定以每个FruitFlower的Fruit属性作为分组依据。
  2. 容器指定:第二个参数HashMap::new 明确要求返回 HashMap 类型,而非默认的通用 Map 实现。
  3. 属性转换:Collectors.mapping(FruitFlower::getFlower, Collectors.toList()) 负责将分组内的FruitFlower对象转换为Flower对象,并收集为 List。
  4. Fruit类的必要性:如果不重写equals()和hashCode(),即使name相同的Fruit对象也会被当作不同的键,导致分组结果不符合预期。

运行输出

Apple: [Rose, Sunflower]
Banana: [Lily, Purple, Rose]

内容的提问来源于stack exchange,提问作者Amit-Chavda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 06:48:19