(ストリームAPIによって)オブジェクトのセット内の属性の文字列の連続したシーケンスを探します

deHaar:

私が取るメソッド記述する必要があります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は、シーケンスの最も最近の発生見つける必要があるクラスの属性の列の値を持っているが。MyEventimplements Comparable<MyEvent>LocalDateTime
List<String>MyEventabbreviation

これは私がこれまでにやっていることです。

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提供するlower1がある場合は、前の要素を取得する方法を、しかし、あなたの要件がサポートしているため、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);
}

したがって、この方法は、すでにすべての要素をトラバースすることなく、最大の要素となり、最初に一致、後方で停止検索します。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=187627&siteId=1