0

I have an ArrayList<Integer> with an even amount of elements. How can I use Stream.forEach to parse 2 values at a time?

x.forEach((a, b) -> System.out.println(a.toString() + "-" + b.toString());

This doesn't work.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
QuaziModo
  • 3
  • 2

3 Answers3

1

You may add the following helper method to some utility class of your project:

public static <T> void forPairs(List<T> list, BiConsumer<T, T> action) {
    IntStream.range(0, list.size()/2)
             .forEach(i -> action.accept(list.get(i*2), list.get(i*2+1)));
}

And use it like this:

List<Integer> list = Arrays.asList(1, 3, 5, 2, 1, 6);
forPairs(list, (a, b) -> System.out.println(a + "-" + b));
Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
1

If you want to use streams for the sake of using streams, you can:

  1. write a quite difficult custom Collector to collect pairs, then re-stream those and perform your operation, or
  2. iterate over indices rather than elements, there are answers provided here (but it would not be a stream of the object that you are interested in).

The problem here is that Streams are designed for stateless pipeline operations without side effects, not for combining elements (some exceptions aside). The docs are quite elaborate.

Using an iterator here would be much more appropriate:

Iterator<Integer> iterator = Arrays.asList(1, 2, 3, 4, 5, 6).iterator();
while(iterator.hasNext()) {
    System.out.println(iterator.next().toString() + "-" + iterator.next().toString());
}

Note: this will throw NoSuchElementException if the list is of odd size. A defensive check is easily written if required.

Boris van Katwijk
  • 2,998
  • 4
  • 17
  • 32
0

This will do the trick:

IntStream.range(0, list.size() - 1)
.filter(i -> i % 2 == 0)
.forEach(i -> System.out.println(list.get(i) + "-" + list.get(i + 1)));

It will produce the following output from list [1, 2, 3, 4, 5, 6]:

1-2
3-4
5-6
Ilya Patrikeev
  • 352
  • 3
  • 10