Reputation: 5921
I have a list of custom objects:
List<CustomObject> customObjects;
from which I would like to extract all the objects that have the have the earliest datetime value set.
So the class would look something like this:
class CustomObject {
LocalDateTime date;
public LocalDateTime getDateTime() {
return date;
}
}
and I'm able to successfully find the object in the list with the earliest date with a custom comparator function like this:
private static LocalDateTime getDate(CustomObject customObject) {
return customObject.getDateTime();
}
CustomObject customObjectMin = customObjects.stream().
min(Comparator.comparing(MyUtilClass::getDate));
However, it is possible to have multiple custom objects with the same date, but it looks like there is no way to get multiple occurrences in that scenario with the min
. Is there an easy solution to finding all the objects in the list with the earliest date set ? Something like this:
List<CustomObject> customObjectsMin = customObjects.stream().
minWithAllOccurences(Comparator.comparing(MyUtilClass::getDate));
Upvotes: 3
Views: 409
Reputation: 4959
Other than Peter Lawrey's excellent answer, I would like to point out that it is possible to do this with a single stream while avoiding the memory costs of collecting every element into a TreeMap. How? One way would be to use reduce()
, as follows:
List<SampleJava> customObjectsMin = customObjects.stream()
.reduce(new ArrayList<>(), // identity
(List<SampleJava> list, SampleJava item) -> { // accumulate
if(list.isEmpty() || getDate(item).compareTo(getDate(list.get(0))) < 0) {
return new ArrayList<>(Arrays.asList(item));
} else if(getDate(item).equals(getDate(list.get(0)))) {
list.add(item);
}
return list;
},
(list1, list2) -> { // combine
if(list1.isEmpty()) return list2;
if(list2.isEmpty()) return list1;
int cmp = getDate(list1.get(0)).compareTo(getDate(list2.get(0)));
if(cmp < 0) return list1;
if(cmp > 0) return list2;
list1.addAll(list2);
return list1;
});
Upvotes: 0
Reputation: 533640
You can do two selections.
e.g.
LocalDate min = customObjects.stream()
.map(CustomObject::getDateTime)
.min(Comparator.naturalOrder());
List<CustomObject> objs = customObjects.stream()
.filter(c -> min.equals(c.getDateTime()))
.collect(Collectors.toList());
Or you can use Collectors.groupingBy into a TreeMap and take the first entry.
Upvotes: 3