3

Is it possible to aggregate two collections one item at a time? For example:

L1: {1,2,3,4}
L2: {1,2,3,4}

I want to aggregate the two, L1 and L2 so that I have a returning

L3: {2, 4, 6, 8}

Hence L3[i] = L2[i] + L3[i]

How can I accomplish this using lambdas?

Olimpiu POP
  • 5,001
  • 4
  • 34
  • 49

4 Answers4

4

You could play with IntStream:

List<Integer> result = IntStream.range(0, Math.min(l1.size(), l2.size()))
                                .map(i -> l1.get(i) + l2.get(i))
                                .boxed()
                                .collect(Collectors.toList());
Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
1

These code snippets do the job:

Solution 1 (simplest approach):

public static Collection<Integer> sumCollectionElements(Collection<Integer> L1, Collection<Integer> L2) {
    final Iterator<Integer> iterator = L2.iterator();
    return L1.stream()
            .limit(Math.min(L1.size(), L2.size()))
            .map(integer -> integer + iterator.next())
            .collect(Collectors.toList());
}

Solution 2 (more general approach -> gist):

public static <A, B, C> Stream<C> zip(Stream<A> streamA, Stream<B> streamB, BiFunction<A, B, C> zipper) {
    final Iterator<A> iteratorA = streamA.iterator();
    final Iterator<B> iteratorB = streamB.iterator();
    final Iterator<C> mergedIterator = new Iterator<C>() {
        @Override
        public boolean hasNext() {
            return iteratorA.hasNext() && iteratorB.hasNext();
        }

        @Override
        public C next() {
            return zipper.apply(iteratorA.next(), iteratorB.next());
        }
    };
    return iteratorToFiniteStream(mergedIterator);
}

public static <T> Stream<T> iteratorToFiniteStream(Iterator<T> iterator) {
    final Iterable<T> iterable = () -> iterator;
    return StreamSupport.stream(iterable.spliterator(), false);
}
Karol Król
  • 3,320
  • 1
  • 34
  • 37
1

If you don't mind using third-party libraries, consider my StreamEx library which enhances standard Java Stream API. Your problem can be solved like this:

List<Integer> l3 = StreamEx.zip(l1, l2, Integer::sum).toList();

At a first glance the StreamEx.zip method is similar to protonpack zip method. However it zips not the streams, but random access lists (like ArrayList or Arrays.asList) which allows proper parallelization. Internally it's close to the @kocko solution with minor differences:

  • If input lists have different size, an IllegalArgumentException will be thrown.
  • Internally the separate spliterator is used which might work somewhat faster in some scenarios.

Also note the usage of toList() method which is a shortcut for collect(Collectors.toList()).

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
-1
L1 = {1,2,3,4}  
L2 = {1,2,3,4}

L3 = map(lambda L1,L2:L1+L2, L1,L2)

Output: [2, 4, 6, 8]
Mayur Koshti
  • 1,794
  • 15
  • 20