Reputation: 45
I've recently started to learn stream API.
I am trying remove duplication from following piece of code.
Is it possible use merge function based on Predicate
or condition?
(Also I was thinking about using partitioningBy
or groupingBy
from Collectors
)
BinaryOperator<LocalDateTime> latestDate = (p, a) -> a.isAfter(p) ? a : p;
BinaryOperator<LocalDateTime> earliestDate = (p, a) -> a.isBefore(p) ? a : p;
Map<Status,LocalDateTime> latest = history.stream()
.filter(isNewOrOpen.negate())
.collect(toMap(History::getStatus,
History::getChangedtetme,
latestDate));
Map<Status,LocalDateTime> earliest = history.stream()
.filter(isNewOrOpen)
.collect(toMap(History::getStatus,
History::getChangedtetme,
earliestDate));
latest.putAll(earliest);
Upvotes: 4
Views: 203
Reputation: 100309
If I understand your problem correctly, isNewOrOpen
predicate uses History.getStatus()
and you want to select the history items with earliest date for new/open status and with latest date for other statuses. It's better to define the Comparator
which implements this logic (it's supposed that h1
and h2
have the same status here):
Comparator<History> comparator = (h1, h2) -> isNewOrOpen.test(h1) ?
h2.getChangedtetme().compareTo(h1.getChangedtetme()):
h1.getChangedtetme().compareTo(h2.getChangedtetme());
Using this comparator, it's quite easy to define the collector to solve your task:
Collector<History, ?, Map<Status, LocalDateTime>> collector
= groupingBy(History::getStatus,
collectingAndThen(maxBy(comparator),
opt -> opt.get().getChangedtetme()));
Note the collectingAndThen
usage: maxBy
returns Optional<History>
and we want to extract the getChangedtetme()
(whatever it means).
So finally you can use this collector directly:
Map<Status, LocalDateTime> result = history.stream().collect(collector);
The latestDate
and earliestDate
seem to be unnecessary.
Upvotes: 2
Reputation: 28056
As you say, you can use Collectors.partitioningBy to do what you want.
BinaryOperator<LocalDateTime> latestDate = (p, a) -> a.isAfter(p) ? a : p;
Map<Boolean, Map<Status,LocalDateTime>> partitions =
history.stream()
.collect(partitioningBy(isNewOrOpen,
toMap(History::getStatus,
History::getChangedtetme,
latestDate));
Map<Status,LocalDateTime> latest = partitions.get(true);
Map<Status,LocalDateTime> earliest = partitions.get(false);
Upvotes: 2