私が取るメソッド記述する必要がありますSortedSet<MyEvent>
とList<String>
。これは、の連続配列があるかどうかを決定しなければならないMyEvent
所与表すList<String>
特定のクラス属性によっては。
のは、以下の(コード - )状況があったと仮定しましょう:
List<String> list = new ArrayList<String>()
list.add("AAA");
list.add("BBB");
と Set<MyEvent>
SortedSet<MyEvent> events = new TreeSet<MyEvent>();
タイプのオブジェクトと(による比較のみ)。与えられたは略語の順序を表し、Iは、シーケンスの最も最近の発生見つける必要があるクラスの属性の列の値を持っているが。MyEvent
implements Comparable<MyEvent>
LocalDateTime
List<String>
MyEvent
abbreviation
これは私がこれまでにやっていることです。
public static void main(String[] args) {
SortedSet<MyEvent> events = generateSomeElements();
List<String> sequence = new ArrayList<>();
sequence.add("AAA");
sequence.add("BBB");
MyEvent desired = getMostRecentLastEventOfSequence(events, sequence);
System.out.println("Result: " + desired.toString());
}
public static MyEvent getMostRecentLastEventOfSequence(SortedSet<MyEvent> events,
List<String> sequence) {
// "convert" the events to a List in order to be able to access indexes
List<MyEvent> myEvents = new ArrayList<MyEvent>();
events.forEach(event -> myEvents.add(event));
// provide a temporary data structure for possible results
SortedSet<MyEvent> possibleReturnValues = new TreeSet<MyEvent>();
// iterate the events in order to find those with a specified predecessor
for (int i = 0; i < myEvents.size(); i++) {
if (i > 0) {
// consider only successive elements
MyEvent a = myEvents.get(i - 1);
MyEvent b = myEvents.get(i);
// check if there is a
if (a.getAbbreviation().equals(sequence.get(0))
&& b.getAbbreviation().equals(sequence.get(1))) {
// if a sequence was found, add the last element to the possible results
possibleReturnValues.add(b);
}
}
}
// check if there were possible results
if (possibleReturnValues.size() == 0) {
return null;
} else {
// if there are any, return the most recent / latest one
return possibleReturnValues.stream().max(MyEvent::compareTo).orElse(null);
}
}
この方法は、(少なくとも、この2要素の配列のために)働いています。
それは、ストリームAPI(とためにシーケンスの未知の大きさ)を使用して、単一の呼び出しでそれを行うことは可能ですか?
あなたの仕事は、単に作成し、それほど難しいことではありませんStream
、適用filter
、および最大値を求めます。そこ私たちは、述語の前の要素を必要とすることの障害はあるが、我々はそれを提供することができますソースコレクション、上の手を持っています。
実際には、すべてのは、SortedSet
また、あるNavigableSet
提供するlower
1がある場合は、前の要素を取得する方法を、しかし、あなたの要件がサポートしているため、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);
}
しかし、我々はそれよりも良い行うことができます。我々は今、我々が最大探しているので、ソート入力、我々は後方に繰り返し処理を行う場合、最初の一致が十分であることを知っています。ここでも、入力が実際にあるとき、非常に滑らかです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);
}
したがって、この方法は、すでにすべての要素をトラバースすることなく、最大の要素となり、最初に一致、後方で停止検索します。