HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaCritical

Is there a concise way to iterate over a stream with indices in Java 8?

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
streamconcisewithjavaoveriteratewayindicesthere

Problem

Is there a concise way to iterate over a stream whilst having access to the index in the stream?

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());


which seems rather disappointing compared to the LINQ example given there

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


Is there a more concise way?

Further it seems the zip has either moved or been removed...

Solution

The cleanest way is to start from a stream of indices:

String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"};
IntStream.range(0, names.length)
         .filter(i -> names[i].length()  names[i])
         .collect(Collectors.toList());


The resulting list contains "Erik" only.

One alternative which looks more familiar when you are used to for loops would be to maintain an ad hoc counter using a mutable object, for example an AtomicInteger:

String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"};
AtomicInteger index = new AtomicInteger();
List list = Arrays.stream(names)
                          .filter(n -> n.length() <= index.incrementAndGet())
                          .collect(Collectors.toList());


Note that using the latter method on a parallel stream could break as the items would not necessarily be processed "in order".

Code Snippets

String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"};
IntStream.range(0, names.length)
         .filter(i -> names[i].length() <= i)
         .mapToObj(i -> names[i])
         .collect(Collectors.toList());
String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"};
AtomicInteger index = new AtomicInteger();
List<String> list = Arrays.stream(names)
                          .filter(n -> n.length() <= index.incrementAndGet())
                          .collect(Collectors.toList());

Context

Stack Overflow Q#18552005, score: 603

Revisions (0)

No revisions yet.