将具有嵌套集合的对象转换为 Java 11 中的对象列表

问题描述 投票:0回答:2

我正在编写一些代码,我需要将具有嵌套集合字段的对象转换为基于这些集合的对象列表。我的起始对象如下所示:

public class Attributes{
    public String id;
    public List<String> optIn;
    public List<String> emailNotifications;
}

我需要将该对象转换为该类的对象列表:

public class LearnerSubscription{
   public String id;
   public String channel;
   public boolean dailyEmails;
   public boolean individualEmails;
}

作为示例,假设一个具有以下数据的 Attributes 对象:

Attribute atr1 = new Attribute();
atr1.id="1";
atr1.optIn=List.of("abc", "xyz", "123");
atr1.emailNotifications=List.of("abc", "123", "trp");

当我运行转换函数时,我想得到以下输出:

[ LearnerSubscription("1", "abc", true, true),
LearnerSubscription("1", "xyz", true, false), 
LearnerSubscription("1", "123", true, true), 
LearnerSubscription("1", "trp", false, true) ]

请注意如何根据通道是否出现在第一个列表(“xyz”)、第二个列表(“trp”)或两者(“abc”、“123”)中来计算布尔值。

我不确定实现这样的功能的最佳方法是什么。我知道我可以简单地暴力破解它;迭代 optIn 和 emailNotifications 中的所有项目并跟踪常见项目。然而,我觉得应该有一个更优雅的解决方案,利用 Java Stream API。对于解决问题的更好方法有什么建议吗?

java collections java-stream
2个回答
1
投票

现在如何给出?不,除了使用 for 循环循环遍历每个选项并在找到它时打破循环之外,没有更快的方法了。但是,如果您的列表是哈希的排序集合,您可以对哈希项进行二分搜索,这会将时间效率提高到 O(log(n))。


0
投票

我们快速分析一下一般需要哪些操作:

  • 您需要将每个属性展平为订阅集合
  • 您需要按属性和频道对订阅进行分组和合并

使用流 API,使用上面的代码,它可能看起来像这样(可能还有更优雅的方法):

Collection<Optional<LearnerSubscription>> subs = Stream.of(atr1)
 //flatten each attribute into a stream of subscriptions
 .flatMap(atr -> Stream.concat(
    //a stream for daily subscriptions
    atr.optIn.stream().map(c -> new LearnerSubscription(atr.id, c, true, false)),
    //a stream for individual subscriptions
    atr.emailNotifications.stream().map(c -> new LearnerSubscription(atr.id, c, false, true))
  ))
 //collect by grouping on attribute id and channel
 .collect(Collectors.groupingBy(s -> Pair.of(s.id, s.channel),
    //reduce by merging subscription a into b
    Collectors.reducing((a, b) -> {
       a.dailyEmails |= b.dailyEmails;
       a.individualEmails |= b.individualEmails;
       return a;
    })))
  //just get the values of the group map (this could further be converted into a list)
 .values(); 

但是,使用流可能并不容易阅读和理解,也不一定更快。

使用循环和映射可能是更好的方法:

(示例即将到来)

© www.soinside.com 2019 - 2024. All rights reserved.