Ваша задача не так сложна, просто создайте Stream
, примените filter
и запросите максимальное значение.Есть препятствие в том, что нам нужен предыдущий элемент в предикате, но у нас есть руки к исходной коллекции, которая может предоставить ее.
На практике каждый SortedSet
также является NavigableSet
, который обеспечиваетlower
метод, чтобы получить предыдущий элемент, если он есть, но так как ваше требование заключается в поддержке ввода SortedSet
, мы должны предоставить запасной вариант для теоретического случая SortedSet
не являясь NavigableSet
.
Тогда операция может быть реализована как
public static MyEvent getMostRecentLastEventOfSequence(
SortedSet<MyEvent> events, List<String> sequence) {
String first = sequence.get(0), second = sequence.get(1);
UnaryOperator<MyEvent> previous;
if (events instanceof NavigableSet) {
NavigableSet<MyEvent> navigableSet = (NavigableSet<MyEvent>) events;
previous = navigableSet::lower;
}
else previous = event -> events.headSet(event).last();
return events.stream()
.filter(event -> event.getAbbreviation().equals(second))
.filter(event -> {
MyEvent p = previous.apply(event);
return p != null && p.getAbbreviation().equals(first);
})
.max(Comparator.naturalOrder()).orElse(null);
}
, но мы можем добиться большего, чем это.Поскольку теперь мы ищем максимум во входе sorted , мы знаем, что первого совпадения достаточно при итерации в обратном направлении.Опять же, это намного более плавно, когда входные данные на самом деле являются NavigableSet
:
public static MyEvent getMostRecentLastEventOfSequence(
SortedSet<MyEvent> events, List<String> sequence) {
String first = sequence.get(0), second = sequence.get(1);
UnaryOperator<MyEvent> previous;
Stream<MyEvent> stream;
if (events instanceof NavigableSet) {
NavigableSet<MyEvent> navigableSet = (NavigableSet<MyEvent>) events;
previous = navigableSet::lower;
stream = navigableSet.descendingSet().stream();
}
else {
previous = event -> events.headSet(event).last();
stream = Stream.iterate(events.last(), previous).limit(events.size());
}
return stream
.filter(event -> event.getAbbreviation().equals(second))
.filter(event -> {
MyEvent p = previous.apply(event);
return p != null && p.getAbbreviation().equals(first);
})
.findFirst().orElse(null);
}
Так что этот метод будет искать в обратном направлении и останавливаться на первом совпадении, которое уже будет максимальным элементом, без необходимостипройти все элементы.