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

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) ]

方案优势

  1. 效率提升:用HashSet替代List做存在性检查,大幅降低查询耗时
  2. 代码简洁:Stream链式调用逻辑清晰,避免嵌套循环的冗余代码
  3. 可读性强:每个操作步骤(合并流、去重、映射、收集)一目了然

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 21:34:54