Java 组合两个列表以形成唯一列表(基于某些字段逻辑)
我有一个具体的问题要解决,需要一些帮助 我有一个包含三个字段的POJO:Java 组合两个列表以形成唯一列表(基于某些字段逻辑),java,list,lambda,java-8,Java,List,Lambda,Java 8,我有一个具体的问题要解决,需要一些帮助 我有一个包含三个字段的POJO: 身份证 日期 加权数 此POJO可以从DB或外部端点填充,并将返回所述POJO的列表。 现在我们得到两个信息相似的独立列表。这些列表将无序且大小不一(有时为空) 如何结合这两个列表,根据ID创建一个唯一的列表? 如果ID相同,请选择具有最新日期的ID 如果ID和日期相同,请选择加权数较高的ID和日期 如果所有的都是一样的,那也没关系——任选一个 我的解决方案非常麻烦,阅读起来也很难看——它包含两个嵌套循环和3对if
- 身份证
- 日期
- 加权数
- 如果ID相同,请选择具有最新日期的ID
- 如果ID和日期相同,请选择加权数较高的ID和日期
- 如果所有的都是一样的,那也没关系——任选一个
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;
}
}
您可以先加入两个列表,然后使用
Comparator
和BinaryOperator.maxBy
获取同一id的max by date,然后使用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());
返回新的ArrayList(
Stream.concat(listOne.Stream(),listwo.Stream())
.collect(Collectors.toMap(MyEntity::getId,Function.identity(),
maxBy(Comparator.comparing(MyEntity::getDate)
.Then比较(MyEntity::getWeightedNumber)))
.values());
以下使用收集器的方法。groupingBy
和收集器。maxBy
应该可以工作:
groupingBy
maxBy
收集器按date
和weightedNumber
进行分组map.Entry
的结果映射转换为List
私有静态列表组合策略(列表一、列表二){
返回Stream.concat(listOne.Stream(),listwo.Stream())
.collect(收集器).groupingBy(MyEntity::getId、,
收藏家.maxBy(
Comparator.comparing(MyEntity::getDate)
.Then比较(MyEntity::getWeightedNumber))
)).entrySet()
.stream()//流
.map(map.Entry::getValue)//获取可选值
.map(可选::get)//从可选
.collect(Collectors.toList());
}
这里有另一种方法可以做到这一点,没有流,但功能强大:
Map<String, MyEntity> map = new LinkedHashMap<>();
Consumer<MyEntity> addAction = e -> map.merge(
e.getId(),
e,
BinaryOperator.maxBy(Comparator.comparing(MyEntity::getDate)
.thenComparing(MyEntity::getWeightedNumber)));
listOne.forEach(addAction);
listTwo.forEach(addAction);
List<MyEntity> result = new ArrayList<>(map.values());
Map Map=newlinkedhashmap();
消费者添加操作=e->map.merge(
e、 getId(),
E
maxBy(Comparator.comparing(MyEntity::getDate)
。然后比较(MyEntity::getWeightedNumber));
listOne.forEach(addAction);
清单2.forEach(addAction);
列表结果=新的ArrayList(map.values());
这将迭代两个列表,并在每个元素上执行
addAction
使用者。addAction
使用者通过应用该方法将实体合并到地图中。两个列表的顺序和/或大小是否始终相同?@jamiebiotti否,顺序和大小可能不同。甚至可能有一个列表为空的情况。如果结果不需要排序,并且可能是无序/未排序的。您的解决方案将如何更改?如果您不想在合并列表之前排序默认顺序是什么?没有默认顺序。这些列表要么来自DB,要么来自RESTAPI——它们的顺序可能会有很大的差异。有时甚至是空的。我的意思是你们想保持列表中的任何顺序吗?如果不是,为什么你不想排序?投票赞成使用BinaryOperator.maxBy
这是一个鲜为人知的非常好的实用程序
Map<String, MyEntity> map = new LinkedHashMap<>();
Consumer<MyEntity> addAction = e -> map.merge(
e.getId(),
e,
BinaryOperator.maxBy(Comparator.comparing(MyEntity::getDate)
.thenComparing(MyEntity::getWeightedNumber)));
listOne.forEach(addAction);
listTwo.forEach(addAction);
List<MyEntity> result = new ArrayList<>(map.values());