0 votes
1 view
in Java by (10.2k points)

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<String> nameList;

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

1 Answer

0 votes
by (46.1k points)

The best method 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() <= i)

         .mapToObj(i -> names[i])

         .collect(Collectors.toList());

The resulting list includes "Erik" barely.

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

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

Note that applying the latter approach on a parallel stream could collapse as the items would not necessarily be treated "in order".

Related questions

0 votes
1 answer
0 votes
1 answer
asked Oct 9, 2019 in Java by Anvi (10.2k points)
0 votes
1 answer
0 votes
1 answer
0 votes
1 answer
Welcome to Intellipaat Community. Get your technical queries answered by top developers !


Categories

...