web-dev-qa-db-de.com

Java 8 Stream: Wie wird das aktuelle Element mit dem nächsten Element verglichen?

Wie erhalte ich mit Java 8-Streams das nächste Element aus einem Listname__?

Wenn ich über einen Listiteriere, möchte ich das aktuelle mit dem nächsten Element der Liste vergleichen.

Ist es mit Java 8 Stream machbar?

14
bhupen

In meiner kostenlosen StreamEx - Bibliothek können Sie die Paare der Stream-Elemente mithilfe der zusätzlichen pairMap - Zwischenoperation bearbeiten. So was:

StreamEx.of(input).pairMap((current, next) -> doSomethingWith(current, next));

Wobei input eine Collection, ein Array oder eine Stream ist. Auf diese Weise können Sie beispielsweise einfach überprüfen, ob die Eingabe sortiert ist:

boolean isSorted = StreamEx.of(input)
                           .pairMap((current, next) -> next.compareTo(current))
                           .allMatch(cmp -> cmp >= 0);

Es gibt auch eine forPairs terminal-Operation, die eine forEach-Analogie zu allen Paaren von Eingangselementen ist:

StreamEx.of(input).forPairs((current, next) -> doSomethingWith(current, next));

Diese Funktionen funktionieren gut mit jeder Streamquelle (entweder Direktzugriff oder nicht) und unterstützen die parallelen Streams vollständig.

13
Tagir Valeev

Eine Möglichkeit ist, einen IntStreamder Indizes zu generieren und die Listname__-Elemente über ihren Index abzurufen. Dies ist nur effizient, wenn Listden Direktzugriff unterstützt (d. H. Wenn Ihr Listein LinkedListist, wäre dies eine schlechte Idee, da list.get(i) keine konstante Zeit benötigt).

Zum Beispiel :

IntStream.range(0,list.size()-1).forEach(i -> {
    doSomething(list.get(i),list.get(i+1));
});

Eine andere Möglichkeit besteht darin, das letzte Element in einem Array zu speichern:

List<Element> list = ...
Element[] arr = new Element[1];
list.stream().forEach(e -> {
    if (arr[0] != null)
        doSomething(arr[0],e); 
    arr[0]=e;
});

Dies funktioniert nur für sequentielle Streams.

10
Eran

Stream.reduce kann je nach Ziel verwendet werden. Wie Sie gesagt haben, möchten Sie fortlaufende Elemente miteinander vergleichen. Folgendes würde "Same 3" drucken:

Stream.of(1,2,3,3).reduce((a,b)->{
    if(a==b) System.out.println("Same "+a);
    return b; // will be "a" for next reduction
});
1
Marc Dzaebel

Sie machen immer eine der folgenden:

  1. Konvertieren Sie Ihren Stream in einen Stream von Elementen, der die "Historie" der letzten Elemente des Streams enthält
  2. Verarbeiten Sie Ihren Stream so, dass das aktuell bearbeitete Element als "nächstes" Element und das zuvor bearbeitete Element als "aktuelles" Element betrachtet wird.

Implementierungen beider Lösungen finden Sie in diesem Thread: Ist es möglich, das nächste Element im Stream zu erhalten?

0
walkeros

Ich musste das Gleiche tun und die Unterschiede der Elemente eines Streams (ursprünglich ein Array) vergleichen. Also habe ich eine Methode als Parameter für den UnaryOperator verwendet, die .map () wie folgt erwartet ... und es hat für mich ohne besondere Gizmos funktioniert:

import Java.util.Arrays;

class streamDiffUtil {
    public static void main(String[] args) {
        int[] elements = {1,2,5};
        int result = Arrays.stream(elements)
                .map(value -> calcMaxDiff(value, elements))
                .max()
                .getAsInt();
        System.out.println(result);
    }

    private static int calcMaxDiff(int j, int[] elements) {
        return Arrays.stream(elements)
                .map(value -> Math.abs(j-value))
                .max().getAsInt();
    }
}

Schön wäre es zu wissen, wie die Methode calcMaxDiff einem UnaryIntOperator in der .map-Signatur entspricht. Das ist ein bisschen jenseits von mir. (.____.) Hoffe, das hilft dir.

0
Beezer

Wenn Sie beispielsweise eine Liste mit Ganzzahlen haben und prüfen möchten, ob sie aufsteigend sortiert sind, können Sie wie folgt vorgehen:

@Test
public void test_listIsSorted() {

    // create integer list for testing purposes: 0,1,2,3, .., 10
    List<Integer> integerList = IntStream.range(0, 10)
            .boxed()
            .collect(Collectors.toList());

    // stream list and compare item n with n+1
    integerList.stream()
            .reduce((integer1, integer2) -> {
                assert integer1 < integer2 : "ordering must be ascending";
                // return second value (which will be processed as "integer1" in the next iteration
                return integer2;
            });

}

Dadurch werden Paare wie (0,1), (1,2), ... verglichen.

0
Georg Moser