【问题标题】:Reduction of List of Objects based on priority of String根据字符串的优先级减少对象列表
【发布时间】:2017-08-15 07:58:39
【问题描述】:

假设我有一个列表List<Foo> mylist = parseFromCSV();

在哪里

parseFromCSV() 

返回Foo 类的对象列表。 Foo 类有她的私有属性:

private mailId;
private status;

... getter 和 setter...

可能是一对对象

mylist: [{MailId=100, Status=BOUNCED, EMAIL=test@test.com},{MailId=100, Status=OPENED, EMAIL=test2@test.com}, {MailId=200, Status=CLICKED, EMAIL = test3@test.com}, {MailId=100, Status=HARDBOUNCED, EMAIL = test4@test.com}]

我的列表中确实可以有重复项,因为列出的对象代表解析为 Java 对象的 CSV 行。 每个 MailId 都有多种不同的可能反馈状态。

我感兴趣的是在我的一组可能状态中为一个 MailId 仅检索 “重要”状态,并将其保存到我的数据库中。

已打开 > 单击 > HARDBOUNCED > BOUNCED(状态的优先级)。

在我的示例中:对于 MailId= 100,我只会将 OPENED 状态保存到数据库中的状态列中。

什么是实现这一目标的好方法?我应该创建一个新的列表(设置?),其中包含每对过滤的 {MailId, Status(Prioritized)}, ... {MailIdN, StatusN(Prioritized)...} 吗?我们可以使用枚举为字符串添加优先级,或者为我的 Foo 类对象创建一个新的比较器吗?

使用hibernate对mysql数据库的持久化操作应该是这样的:

persistStatusIntoTable(String MailId, String Status(Taken only status based on priority))

感谢大家的帮助!

【问题讨论】:

  • 我建议将状态作为其自己的单独类,该类具有私有 int 优先级(或类似的东西),使用自定义 Comparator 也可以,但可能很难如果您添加更多状态,请制作。 (在一些奇怪的情况下。)然后创建一个新 List 并将 myList 中的所有元素添加到它,这些元素通过您的状态优先条件。
  • 我认为把它变成一个单独的类是个坏主意,因为状态代表我的实体类 FeedBackReceived 的一个字段。我想我应该像你说的那样继续制作自定义 Comparator 。我可以拥有的可能状态都设置为我提到的那些。比较器将是通用的,并适用于具有不同类型对象的其他现有列表,其中还包括状态。我有 List、List、List 代表不同的电子邮件帐户
  • 感谢您的回答和时间。 @Dolev 你对桌子是什么意思?数据库表?

标签: java hibernate data-structures java-8 reduce


【解决方案1】:

我在这里假设了几件事(可以很容易地改变)。首先Status 是一个枚举(但你可以对String 做同样的事情)。

然后我使用 google guava Ordering 来简化 Comparator 的构建(没有它你也可以这样做)。

 Comparator<Status> c = Ordering.explicit(
            ImmutableList.of(Status.OPENED, Status.CLICKED, Status.HARDBOUNCED, Status.BOUNCED));

    List<Foo> list = Stream.of(new Foo(Status.BOUNCED, 57), new Foo(Status.OPENED, 57),
            new Foo(Status.CLICKED, 58), new Foo(Status.BOUNCED, 57),
            new Foo(Status.HARDBOUNCED, 58))
            .collect(Collectors.groupingBy(Foo::getId,
                    Collectors.mapping(Foo::getStatus, Collectors.toCollection(() -> new PriorityQueue<>(c)))))
            .entrySet()
            .stream()
            .map(e -> new Foo(e.getValue().remove(), e.getKey()))
            .collect(Collectors.toList());

    System.out.println(list); // [id = 57 status = OPENED, id = 58 status = CLICKED]

这个想法是创建一个Comparator 来定义你的Statuses 的顺序;然后使用该比较器填充PriorityQueue(对于某些id);最终我只对第一个感兴趣 - 正如你所说的最重要(根据比较器,这是第一个)。

这是使用String 而不是enum 用于Status 的版本:

 Comparator<String> c = Ordering.explicit(
            ImmutableList.of("OPENED", "CLICKED", "HARDBOUNCED", "BOUNCED"));

    List<Foo> list = Stream.of(new Foo("BOUNCED", 57), new Foo("OPENED", 57),
            new Foo("CLICKED", 58), new Foo("BOUNCED", 57),
            new Foo("HARDBOUNCED", 58))
            .collect(Collectors.groupingBy(Foo::getId,
                    Collectors.mapping(Foo::getStatus, Collectors.toCollection(() -> new PriorityQueue<>(c)))))
            .entrySet()
            .stream()
            .map(e -> new Foo(e.getValue().remove(), e.getKey()))
            .collect(Collectors.toList());

【讨论】:

  • 非常感谢您的解决方案无疑是正确的并解决了我的问题,但是我勾选了上面的答案,因为它不需要任何第三个库,在我的情况下我不想使用。我相信它会在未来帮助别人!但是再次感谢您!
【解决方案2】:

如果您不想使用 3rd 方库并且不想使用枚举类:

// initialization which you will have to do once somewhere in your code
List<String> ordering = Arrays.asList("OPENED", "CLICKED", "HARDBOUNCED", "BOUNCED");
Map<String, Integer> priorityMap = IntStream.range(0, ordering.size()).boxed()
        .collect(Collectors.toMap(ordering::get, i -> i));

// example input
List<Foo> myList = Arrays.asList(
        new Foo("100", "BOUNCED"), new Foo("100", "OPENED"),
        new Foo("101", "BOUNCED"), new Foo("101", "HARDBOUNCED"), new Foo("101", "BOUNCED"));

// determine foo objects that should be persisted 
Collection<Foo> toBePersisted = myList.stream()
        .filter(t -> priorityMap.containsKey(t.getStatus()))
        .collect(Collectors.toMap(Foo::getMailId, t -> t,
                BinaryOperator.minBy(Comparator.comparing(t -> priorityMap.get(t.getStatus())))))
        .values();

这段代码的作用是:

  • 设置将状态映射到优先级的映射(较低的 int = 较高的优先级)
  • 过滤状态无效的 Foo 实例
  • 按 mailId 分组 Foo 实例
  • 为每个组保留 Foo 实例的最小优先级整数(= 最高优先级)
  • 获取结果地图的值

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-25
    • 2015-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-10
    • 2022-11-21
    • 2022-11-21
    相关资源
    最近更新 更多