'filter objects based on an ID and Date Java
I have a class that for which each instance has a unique Id, a name and update date.
ID | NAME | UPDATE DATE |
---|---|---|
1200 | ANNA* | 2022-03-01 |
1300 | JONH* | 2022-04-01 |
1200 | ANNA* | 2022-04-01 |
1400 | CARL | 2022-01-01 |
1400 | CARL | 2022-02-01 |
1300 | JONH* | 2022-02-01 |
1500 | MARY | 2022-03-01 |
1500 | MARY | 2022-04-01 |
I want only one register from ANNA and JOHN using the most recent date, like this:
ID | NAME | UPDATE DATE |
---|---|---|
1300 | JONH* | 2022-04-01 |
1200 | ANNA* | 2022-04-01 |
1400 | CARL | 2022-01-01 |
1400 | CARL | 2022-02-01 |
1500 | MARY | 2022-03-01 |
1500 | MARY | 2022-04-01 |
I try this way:
List<Document> filteredDocuments = DocumentData
.stream()
.filter(f -> f.getId() == 1200 || f.getId() == 1300)
.collect(groupingBy(g -> g.getId(),
collectingAndThen(maxBy(Comparator.comparing(c -> c.getUpdateDate())), Optional::get)))
.values().stream().collect(toList());
but this filter all the ID and this is not what I want. I need that the others register don't be filtered.
How filter this using the Java 8 Stream API?
Solution 1:[1]
Here is one approach.
- create a
Set
of targetIds - create a map with the Id as key - use
groupingBy
to group by Id - Use
collectingAndThen
to post process the lists- for each list
- if the set contains the id of a list member,
- sort the list in descending order and return the first one in a new List
- else return the original list
- then post process the map by collecting the map values into a List of users.
- for each list
Data declaration
List<User> users =
List.of(new User(1200, "ANNA", "2022-03-01"),
new User(1300, "JOHN", "2022-04-01"),
new User(1200, "ANNA", "2022-04-01"),
new User(1400, "CARL", "2022-01-01"),
new User(1400, "CARL", "2022-02-01"),
new User(1300, "JOHN", "2022-02-01"),
new User(1500, "MARY", "2022-03-01"),
new User(1500, "MARY", "2022-04-01"));
Set<Integer> targetIds = Set.of(1200, 1300);
The solution from list to map to list
List<User> result = users.stream()
.collect(Collectors.groupingBy(User::getId,
Collectors.collectingAndThen(
Collectors.toList(),
lst -> {
if (targetIds.contains(lst.get(0).getId())) {
lst.sort(Comparator.comparing(User::getDate)
.reversed());
return List.of(lst.get(0));
}
return lst;
})))
.values().stream().flatMap(List::stream).toList();
result.forEach(System.out::println);
prints
[1200, ANNA, 2022-04-01]
[1300, JOHN, 2022-04-01]
[1400, CARL, 2022-01-01]
[1400, CARL, 2022-02-01]
[1500, MARY, 2022-03-01]
[1500, MARY, 2022-04-01]
User class definition
class User {
int id;
String name;
LocalDate date;
public User(int id, String name, String date) {
this.id = id;
this.name = name;
this.date = LocalDate.parse(date);
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public LocalDate getDate() {
return date;
}
@Override
public String toString() {
return String.format("[%s, %s, %s]", id, name, date);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | WJS |