将两个列表组合成一个唯一的列表(基于一定的字段逻辑)

Leo*_*Leo 5 java lambda list java-8

我有一个我正在尝试解决的特定问题,需要一些帮助。

我有一个包含三个字段的 POJO:

  • ID
  • 日期
  • 加权数

此 POJO 可以从数据库或外部端点填充,并将返回所述 POJO 的列表。现在我们最终得到两个具有相似信息的单独列表。这些列表将无序且大小不同(有时为空)。

如何根据 ID 组合这两个列表以创建一个唯一的列表?

  • 如果 ID 相同,请选择日期最晚的那个
  • 如果 ID 和日期相同,请选择权重较高的那个
  • 如果全部相同,则无所谓 - 选择两者之一。

我的解决方案非常繁琐且难以阅读 - 它涉及两个嵌套循环和 3 对 if-else 语句。有没有更好的方法,更有效的方法。

下面是一些示例代码:

import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class Scrap2 {

    public static void main(String[] args) {

        MyEntity one = new MyEntity("A", new Date(2020 - 1900, Calendar.SEPTEMBER, 25), 10);
        MyEntity two = new MyEntity("B", new Date(2020 - 1900, Calendar.SEPTEMBER, 25), 10);
        MyEntity three = new MyEntity("C", new Date(2020 - 1900, Calendar.SEPTEMBER, 25), 10);
        MyEntity four = new MyEntity("D", new Date(2020 - 1900, Calendar.SEPTEMBER, 25), 10);

        List<MyEntity> listOne = Arrays.asList(one, two, three, four);

        MyEntity aaa = new MyEntity("A", new Date(2020 - 1900, Calendar.SEPTEMBER, 25), 10);
        MyEntity bbb = new MyEntity("B", new Date(2020 - 1900, Calendar.OCTOBER, 25), 20);
        MyEntity ccc = new MyEntity("D", new Date(2020 - 1900, Calendar.SEPTEMBER, 25), 20);
        MyEntity ddd = new MyEntity("E", new Date(2020 - 1900, Calendar.SEPTEMBER, 25), 20);

        List<MyEntity> listTwo = Arrays.asList(aaa, bbb, ccc, ddd);

        for (MyEntity listItem : combineTwoLists(listOne, listTwo)) {
            System.out.println(listItem);
        }

    }

    private static List<MyEntity> combineTwoLists(List<MyEntity> listOne, List<MyEntity> listTwo) {
       
        return Arrays.asList(listOne.get(0), listTwo.get(1), listOne.get(2), listTwo.get(2), listTwo.get(3));
    }
}


class MyEntity {

    private final String id;
    private final Date date;
   private final Integer weightedNumber;

    public MyEntity(String id, Date date, Integer weightedNumber) {
        this.id = id;
        this.date = date;
        this.weightedNumber = weightedNumber;
    }

    @Override
    public String toString() {
        return "MyEntity{" +
                "id='" + id + '\'' +
                ", date=" + date +
                ", weightedNumber=" + weightedNumber +
                '}';
    }

    public String getId() {
        return id;
    }

    public Date getDate() {
        return date;
    }

    public Integer getWeightedNumber() {
        return weightedNumber;
    }
}
Run Code Online (Sandbox Code Playgroud)

输出应该是这样的(可以是无序/无序的):

MyEntity{id='A', date=Fri Sep 25 2020, weightedNumber=10} 
MyEntity{id='B', date=Sun Oct 25 2020, weightedNumber=20} 
MyEntity{id='C', date=Fri Sep 25 2020, weightedNumber=10} 
MyEntity{id='D', date=Fri Sep 25 2020, weightedNumber=20} 
MyEntity{id='E', date=Fri Sep 25 2020, weightedNumber=20}
Run Code Online (Sandbox Code Playgroud)

Ekl*_*vya 5

您可以先加入两个列表,然后按日期获取最大值,然后使用ComparatorwithBinaryOperator.maxBy为相同的 id 创建一个映射Collectors.toMap。然后在新的 ArrayList 中获取映射的值。

return new ArrayList<MyEntity>(
    Stream.concat(listOne.stream(), listTwo.stream())
          .collect(Collectors.toMap(MyEntity::getId, Function.identity(),
                   BinaryOperator.maxBy(Comparator.comparing(MyEntity::getDate)
                                          .thenComparing(MyEntity::getWeightedNumber))))
          .values());
Run Code Online (Sandbox Code Playgroud)