Stream.skip-Verhalten bei ungeordnetem Terminalbetrieb

Ich habe schon gelesenDie undDie Fragen, aber immer noch Zweifel, ob das beobachtete Verhalten vonStream.skip wurde von JDK-Autoren beabsichtigt.

Lassen Sie uns einfach die Zahlen 1..20 eingeben:

List<Integer> input = IntStream.rangeClosed(1, 20).boxed().collect(Collectors.toList());

Jetzt erstellen wir einen parallelen Stream, kombinieren dasunordered() mitskip() auf verschiedene Arten und sammle das Ergebnis:

System.out.println("skip-skip-unordered-toList: "
        + input.parallelStream().filter(x -> x > 0)
            .skip(1)
            .skip(1)
            .unordered()
            .collect(Collectors.toList()));
System.out.println("skip-unordered-skip-toList: "
        + input.parallelStream().filter(x -> x > 0)
            .skip(1)
            .unordered()
            .skip(1)
            .collect(Collectors.toList()));
System.out.println("unordered-skip-skip-toList: "
        + input.parallelStream().filter(x -> x > 0)
            .unordered()
            .skip(1)
            .skip(1)
            .collect(Collectors.toList()));

er @Filtering-Schritt bewirkt hier im Wesentlichen nichts, erhöht jedoch die Schwierigkeit für die Stream-Engine: Jetzt ist die genaue Größe der Ausgabe nicht mehr bekannt, sodass einige Optimierungen deaktiviert sind. Ich habe folgende Ergebnisse:

skip-skip-unordered-toList: [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
// absent values: 1, 2
skip-unordered-skip-toList: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20]
// absent values: 1, 15
unordered-skip-skip-toList: [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20]
// absent values: 7, 18

Die Ergebnisse sind völlig in Ordnung, alles funktioniert wie erwartet. Im ersten Fall habe ich darum gebeten, zuerst zwei Elemente zu überspringen und dann in einer bestimmten Reihenfolge zu sammeln, um sie aufzulisten. Im zweiten Fall habe ich darum gebeten, das erste Element zu überspringen, dann ungeordnet zu werden und ein weiteres Element zu überspringen (es ist mir egal, welches). Im dritten Fall habe ich zuerst in den ungeordneten Modus gewechselt und dann zwei beliebige Elemente übersprungen.

Lassen Sie uns ein Element überspringen und im ungeordneten Modus in der benutzerdefinierten Sammlung sammeln. Unsere benutzerdefinierte Sammlung wird ein @ seHashSet:

System.out.println("skip-toCollection: "
        + input.parallelStream().filter(x -> x > 0)
        .skip(1)
        .unordered()
        .collect(Collectors.toCollection(HashSet::new)));

Die Ausgabe ist zufriedenstellend:

skip-toCollection: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
// 1 is skipped

So im Allgemeinen erwarte ich, dass, solange Stream bestellt wird,skip() überspringt die ersten Elemente, andernfalls werden beliebige Elemente übersprungen.

Lassen Sie uns jedoch eine entsprechende ungeordnete Terminaloperation verwendencollect(Collectors.toSet()):

System.out.println("skip-toSet: "
        + input.parallelStream().filter(x -> x > 0)
            .skip(1)
            .unordered()
            .collect(Collectors.toSet()));

Nun ist die Ausgabe:

skip-toSet: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20]
// 13 is skipped

Das gleiche Ergebnis kann mit jedem anderen ungeordneten Terminalbetrieb erzielt werden (wieforEach, findAny, anyMatch, etc.). @ Entfernunordered() step ändert in diesem Fall nichts. Scheint, dass währendunordered() step bewirkt, dass der Stream ab der aktuellen Operation nicht mehr in der richtigen Reihenfolge angezeigt wird. Die ungeordnete Terminal-Operation bewirkt, dass der gesamte Stream von Anfang an nicht mehr in der richtigen Reihenfolge angezeigt wird, obwohl dies das Ergebnis beeinflussen kann, wennskip() wurde benutzt. Das erscheint mir völlig irreführend: Ich gehe davon aus, dass die Verwendung des ungeordneten Sammlers das Gleiche ist, als würde man den Stream in einen ungeordneten Modus umwandeln.nur vor dem Terminalbetrieb und den gleichwertigen bestellten Sammler verwenden.

Also meine Fragen sind:

st dieses Verhalten beabsichtigt oder ist es ein FehleWenn ja, ist es irgendwo dokumentiert? Ich habe gelesen Stream.skip () documentation: sagt nichts über ungeordnete Terminaloperationen aus. Ebenfalls Characteristics.UNORDEREDie @ -Dokumentation ist nicht sehr verständlich und besagt nicht, dass die Bestellung für den gesamten Stream verloren geht. Schließlich,Bestelluner Abschnitt @ in der Paketübersicht behandelt auch diesen Fall nicht. Vermutlich fehlt mir etwas?Wenn beabsichtigt ist, dass ein ungeordneter Terminalbetrieb den gesamten Stream ungeordnet macht, warumunordered() step macht es erst seit diesem Zeitpunkt ungeordnet? Kann ich mich auf dieses Verhalten verlassen? Oder hatte ich einfach Glück, dass meine ersten Tests gut funktionieren?

Antworten auf die Frage(4)

Ihre Antwort auf die Frage