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...

1voto

Jean-Baptiste Yunès Punkte 32300

Ein möglicher Weg besteht darin, jedes Element im Fluss zu indizieren:

AtomicInteger index = new AtomicInteger();
Stream.of(names)
  .map(e->new Object() { String n=e; public i=index.getAndIncrement(); })
  .filter(o->o.n.length()<=o.i) // oder mach was du willst mit den Paaren...
  .forEach(o->System.out.println("idx:"+o.i+" nam:"+o.n));

Die Verwendung einer anonymen Klasse entlang eines Streams wird nicht häufig verwendet, ist jedoch sehr nützlich.

1voto

Kaplan Punkte 1226

Sie brauchen nicht unbedingt eine Karte dafür
das ist das nächstgelegene Lambda zum LINQ-Beispiel:

int[] idx = new int[] { 0 };
Stream.of(names)
    .filter(name -> name.length() <= idx[0]++)
    .collect(Collectors.toList());

1voto

B. Stackhouse Punkte 477

Wenn Sie den Index in der forEach-Schleife benötigen, bietet dies eine Möglichkeit.

  public class IndexedValue {

    private final int    index;
    private final Object value;

    public IndexedValue(final int index, final Object value) { 
        this.index = index;
        this.value = value;
    }

    public int getIndex() {
        return index;
    }

    public Object getValue() {
        return value;
    }
}

Verwenden Sie es dann wie folgt.

@Test
public void withIndex() {
    final List list = Arrays.asList("a", "b");
    IntStream.range(0, list.size())
             .mapToObj(index -> new IndexedValue(index, list.get(index)))
             .forEach(indexValue -> {
                 System.out.println(String.format("%d, %s",
                                                  indexValue.getIndex(),
                                                  indexValue.getValue().toString()));
             });
}

0voto

Steven Spungin Punkte 22085

Diese Frage (Stream-Weg, um den Index des ersten Elements abzugleichen Boolescher Wert zu erhalten) hat die aktuelle Frage als Duplikat markiert, deshalb kann ich sie dort nicht beantworten; ich beantworte sie hier.

Hier ist eine generische Lösung, um den übereinstimmenden Index zu erhalten, der keine externe Bibliothek erfordert.

Wenn Sie eine Liste haben.

public static  int indexOf(List items, Predicate matches) {
        return IntStream.range(0, items.size())
                .filter(index -> matches.test(items.get(index)))
                .findFirst().orElse(-1);
}

Und rufen Sie es so auf:

int index = indexOf(myList, item->item.getId()==100);

Und wenn Sie eine Sammlung verwenden, versuchen Sie es damit.

   public static  int indexOf(Collection items, Predicate matches) {
        int index = -1;
        Iterator it = items.iterator();
        while (it.hasNext()) {
            index++;
            if (matches.test(it.next())) {
                return index;
            }
        }
        return -1;
    }

0voto

alexpfx Punkte 5814

Sie können eine statische innere Klasse erstellen, um den Indexer zu kapseln, wie ich es im folgenden Beispiel tun musste:

static class Indexer {
    int i = 0;
}

public static String getRegex() {
    EnumSet range = EnumSet.allOf(MeasureUnit.class);
    StringBuilder sb = new StringBuilder();
    Indexer indexer = new Indexer();
    range.stream().forEach(
            measureUnit -> {
                sb.append(measureUnit.acronym);
                if (indexer.i < range.size() - 1)
                    sb.append("|");

                indexer.i++;
            }
    );
    return sb.toString();
}

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