[英]Java 8 Streams reduce remove duplicates keeping the most recent entry
I have a Java bean, like 我有一个Java bean,例如
class EmployeeContract {
Long id;
Date date;
getter/setter
}
If a have a long list of these, in which we have duplicates by id but with different date, such as: 如果其中有很长的列表,其中我们有ID重复但日期不同的重复项,例如:
1, 2015/07/07
1, 2018/07/08
2, 2015/07/08
2, 2018/07/09
How can I reduce such a list keeping only the entries with the most recent date, such as: 如何减少这样的列表,使其仅保留具有最新日期的条目,例如:
1, 2018/07/08
2, 2018/07/09
? ? Preferably using Java 8... 最好使用Java 8 ...
I've started with something like: 我从类似以下内容开始:
contract.stream()
.collect(Collectors.groupingBy(EmployeeContract::getId, Collectors.mapping(EmployeeContract::getId, Collectors.toList())))
.entrySet().stream().findFirst();
That gives me the mapping within individual groups, but I'm stuck as to how to collect that into a result list - my streams are not too strong I'm afraid... 这使我可以在各个组中进行映射,但是我对如何将其收集到结果列表中感到困惑-恐怕我的流不太强...
Well, I am just going to put my comment here in the shape of an answer: 好吧,我将在这里以回答的形式发表我的评论:
yourList.stream()
.collect(Collectors.toMap(
EmployeeContract::getId,
Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(EmployeeContract::getDate)))
)
.values();
This will give you a Collection
instead of a List
, if you really care about this. 如果您真的很在意这会给您一个Collection
而不是一个List
。
You can do it in two steps as follows : 您可以按照以下两个步骤进行操作:
List<EmployeeContract> finalContract = contract.stream() // Stream<EmployeeContract>
.collect(Collectors.toMap(EmployeeContract::getId,
EmployeeContract::getDate, (a, b) -> a.after(b) ? a : b)) // Map<Long, Date> (Step 1)
.entrySet().stream() // Stream<Entry<Long, Date>>
.map(a -> new EmployeeContract(a.getKey(), a.getValue())) // Stream<EmployeeContract>
.collect(Collectors.toList()); // Step 2
First step : ensures the comparison of date
s with the most recent one mapped to an id
. 第一步 :确保将date
s与映射到id
的date
进行比较。
Second step : maps these key, value pairs to a final List<EmployeeContract>
as a result. 第二步 :将这些键值对映射到最终的List<EmployeeContract>
。
Just to complement the existing answers, as you're asking: 您只想补充现有的答案,就可以:
how to collect that into a result list 如何将其收集到结果列表中
Here are some options: 以下是一些选项:
Wrap the values()
into an ArrayList
: 将values()
包装到ArrayList
:
List<EmployeeContract> list1 = new ArrayList<>(list.stream() .collect(toMap(EmployeeContract::getId, identity(), maxBy(comparing(EmployeeContract::getDate)))) .values());
Wrap the toMap
collector into collectingAndThen
: 将toMap
收集器包装到collectingAndThen
:
List<EmployeeContract> list2 = list.stream() .collect(collectingAndThen(toMap(EmployeeContract::getId, identity(), maxBy(comparing(EmployeeContract::getDate))), c -> new ArrayList<>(c.values())));
Collect the values
to a new List
using another stream: 使用另一个流将values
收集到新的List
中:
List<EmployeeContract> list3 = list.stream() .collect(toMap(EmployeeContract::getId, identity(), maxBy(comparing(EmployeeContract::getDate)))) .values() .stream() .collect(toList());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.