Tomek Tomek - 6 months ago 12
Java Question

Keep track of iteration with parametrized Stream

This code:

Kid[] kids = Kid.getSimpleArray();
String names = Stream.of(kids)
.filter(Kid::hasToy)
.map(Kid::getSurname)
.collect(Collectors.joining(", "));
out.println(names);


gives me this result:

Stępień, Inglot, Czubówna, Lepiej, Łagowska

And I'm thinking of a solution to make it like this:

1.Stępień, 2.Inglot, 3.Czubówna, 4.Lepiej, 5.Łagowska

P.S I couldn't think of a better question to get answer I'm looking for.

Answer

Note that this is really ugly and not an advice I should give here but here it is.

You may use a temporary collection that will serve us as a counter. The advantage is that we can block the reference as final but still add elements to it.

We add whatever to it each time a Kid passes the filter and get the size for the integer in your String.

final List tmp = new ArrayList();
Kid[] kids = Kid.getSimpleArray();
String names = Stream.of(kids)
                .filter(Kid::hasToy)
                .peek(x -> tmp.add(1))
                .map(x -> tmp.size() + "." + x.getSurname())
                .collect(Collectors.joining(", "));
out.println(names);

EDIT

Here are two other solutions provided by @Sam and @Tunaki


@Sam

final AtomicInteger ai = new AtomicInteger();
Kid[] kids = Kid.getSimpleArray();
String names = Stream.of(kids)
                .filter(Kid::hasToy)
                .map(x -> ai.incrementAndGet() + "." + x.getSurname())
                .collect(Collectors.joining(", "));
out.println(names);

@Tunaki

Kid[] kids = Kid.getSimpleArray();
Kid[] filteredKids = Arrays.stream(kids).filter(Kid::hasToy).toArray(Kid[]::new);
String names = IntStream.range(0, filteredKids.length)
                        .mapToObj(i -> i + "." + filteredKids[i].getSurname())
                        .collect(Collectors.joining(", ");
out.println(names);
Comments