如何用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); }); } }
关键说明
- 分组逻辑:
Collectors.groupingBy(FruitFlower::getFruit)指定以每个FruitFlower的Fruit属性作为分组依据。 - 容器指定:第二个参数
HashMap::new明确要求返回 HashMap 类型,而非默认的通用 Map 实现。 - 属性转换:
Collectors.mapping(FruitFlower::getFlower, Collectors.toList())负责将分组内的FruitFlower对象转换为Flower对象,并收集为 List。 - Fruit类的必要性:如果不重写
equals()和hashCode(),即使name相同的Fruit对象也会被当作不同的键,导致分组结果不符合预期。
运行输出
Apple: [Rose, Sunflower] Banana: [Lily, Purple, Rose]
内容的提问来源于stack exchange,提问作者Amit-Chavda
相关产品推荐
相关产品推荐

