514 Stimmen

Gibt es eine prägnante Möglichkeit, über einen Stream mit Indizes in Java 8 zu iterieren?

Gibt es einen prägnanten Weg, über einen Stream zu iterieren und dabei Zugriff auf den Index im Stream zu haben?

String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};

List nameList;
Stream indices = intRange(1, names.length).boxed();
nameList = zip(indices, stream(names), SimpleEntry::new)
        .filter(e -> e.getValue().length() <= e.getKey())
        .map(Entry::getValue)
        .collect(toList());

was im Vergleich zum dort gegebenen LINQ-Beispiel recht enttäuschend erscheint

string[] names = { "Sam", "Pamela", "Dave", "Pascal", "Erik" };
var nameList = names.Where((c, index) => c.Length <= index + 1).ToList();

Gibt es einen prägnanteren Weg?

Zudem scheint es, dass zip entweder verschoben oder entfernt wurde...

13voto

Tagir Valeev Punkte 91975

Nur der Vollständigkeit halber hier die Lösung mit meiner StreamEx -Bibliothek:

String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"};
EntryStream.of(names)
    .filterKeyValue((idx, str) -> str.length() <= idx+1)
    .values().toList();

Hier erstellen wir einen EntryStream , der Stream> erweitert und spezifische Operationen wie filterKeyValue oder values hinzufügt. Außerdem wird der toList() -Shortcut verwendet.

12voto

alex.b Punkte 1338

Ich habe die Lösungen hier gefunden, als der Stream aus einer Liste oder einem Array erstellt wird (und du die Größe kennst). Aber was ist, wenn der Stream eine unbekannte Größe hat? In diesem Fall versuchen Sie diese Variante:

public class WithIndex {
    private int index;
    private T value;

    WithIndex(int index, T value) {
        this.index = index;
        this.value = value;
    }

    public int index() {
        return index;
    }

    public T value() {
        return value;
    }

    @Override
    public String toString() {
        return value + "(" + index + ")";
    }

    public static  Function> indexed() {
        return new Function>() {
            int index = 0;
            @Override
            public WithIndex apply(T t) {
                return new WithIndex<>(index++, t);
            }
        };
    }
}

Verwendung:

public static void main(String[] args) {
    Stream stream = Stream.of("a", "b", "c", "d", "e");
    stream.map(WithIndex.indexed()).forEachOrdered(e -> {
        System.out.println(e.index() + " -> " + e.value());
    });
}

9voto

V0idst4r Punkte 91

Mit einer Liste können Sie es versuchen

List strings = new ArrayList<>(Arrays.asList("Erster", "Zweiter", "Dritter", "Vierter", "Fünfter")); // Ein Beispiel für eine Liste von Strings
strings.stream() // Die Liste in einen Stream umwandeln
    .collect(HashMap::new, (h, o) -> h.put(h.size(), o), (h, o) -> {}) // Erstellen Sie eine Zuordnung des Index zum Objekt
        .forEach((i, o) -> { // Jetzt können wir ein BiConsumer forEach verwenden!
            System.out.println(String.format("%d => %s", i, o));
        });

Ausgabe:

0 => Erster
1 => Zweiter
2 => Dritter
3 => Vierter
4 => Fünfter

6voto

Grzegorz Piwowarek Punkte 12514

Wenn Sie zufällig Vavr (früher bekannt als Javaslang) verwenden, können Sie die dedizierte Methode nutzen:

Stream.of("A", "B", "C")
  .zipWithIndex();

Wenn wir den Inhalt ausgeben, sehen wir etwas Interessantes:

Stream((A, 0), ?)

Dies liegt daran, dass Streams träge sind und wir keine Ahnung über die nächsten Elemente im Stream haben.

4voto

user_3380739 Punkte 1495

Hier ist der Code von abacus-common

Stream.of(names).indexed()
      .filter(e -> e.value().length() <= e.index())
      .map(Indexed::value).toList();

Offenlegung Ich bin der Entwickler von abacus-common.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X