Java 11中如何将含嵌套集合的对象转换为对象列表?
基于Java Stream API实现Attribute到LearnerSubscription的优雅转换
类定义回顾
先明确涉及的两个类结构:
Attribute类
public class Attribute { public String id; public List<String> optIn; public List<String> emailNotifications; }
LearnerSubscription类
public class LearnerSubscription { public String id; public String channel; public boolean dailyEmails; public boolean individualEmails; }
转换规则
- 若channel存在于
optIn列表,dailyEmails设为true - 若channel存在于
emailNotifications列表,individualEmails设为true - 需覆盖两个列表中所有唯一的channel,生成对应的
LearnerSubscription对象列表
优雅实现方案(基于Stream API)
核心思路是合并两个列表的流、去重,再映射为目标对象,同时用Set优化查询效率:
import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; public class AttributeConverter { public List<LearnerSubscription> convert(Attribute attribute) { // 将List转为Set,把contains操作的时间复杂度从O(n)降为O(1) Set<String> optInSet = new HashSet<>(attribute.optIn); Set<String> emailNotificationsSet = new HashSet<>(attribute.emailNotifications); return Stream.concat(attribute.optIn.stream(), attribute.emailNotifications.stream()) .distinct() // 去重,确保每个channel只处理一次 .map(channel -> { LearnerSubscription subscription = new LearnerSubscription(); subscription.id = attribute.id; subscription.channel = channel; subscription.dailyEmails = optInSet.contains(channel); subscription.individualEmails = emailNotificationsSet.contains(channel); return subscription; }) .collect(Collectors.toList()); } }
简化优化(如果LearnerSubscription有构造器)
如果给LearnerSubscription添加全参构造器:
public LearnerSubscription(String id, String channel, boolean dailyEmails, boolean individualEmails) { this.id = id; this.channel = channel; this.dailyEmails = dailyEmails; this.individualEmails = individualEmails; }
那么映射逻辑可以进一步简化:
.map(channel -> new LearnerSubscription( attribute.id, channel, optInSet.contains(channel), emailNotificationsSet.contains(channel) ))
示例验证
用题目给出的测试数据调用convert方法:
Attribute atr1 = new Attribute(); atr1.id = "1"; atr1.optIn = List.of("abc", "xyz", "123"); atr1.emailNotifications = List.of("abc", "123", "trp"); List<LearnerSubscription> result = new AttributeConverter().convert(atr1);
得到的结果与题目期望完全一致:
[ LearnerSubscription("1", "abc", true, true), LearnerSubscription("1", "xyz", true, false), LearnerSubscription("1", "123", true, true), LearnerSubscription("1", "trp", false, true) ]
方案优势
- 效率提升:用HashSet替代List做存在性检查,大幅降低查询耗时
- 代码简洁:Stream链式调用逻辑清晰,避免嵌套循环的冗余代码
- 可读性强:每个操作步骤(合并流、去重、映射、收集)一目了然
内容的提问来源于stack exchange,提问作者pbuchheit
相关产品推荐
相关产品推荐

