Iterating over two lists using Java 8 streams
The canonical solution to convert nested loops for
to is Stream
used via flatMap
:
return rootObj.getListA().stream()
.flatMapToInt(objA->objA.getListB().stream()
.mapToInt(objB->objB.getCount() * objA.getCount()))
.sum();
This allows the operation to be performed for every inner iteration. However, in the special case of summation, you can simplify the operation, since it doesn't matter if you calculate (a+b+c+d)
or (a+b)+(c+d)
:
return rootObj.getListA().stream()
.mapToInt(objA->objA.getListB().stream()
.mapToInt(objB->objB.getCount() * objA.getCount()).sum())
.sum();
And when we remember elementary arithmetic, we must also remember what (a*x)+(b*x)
is equal (a+b)*x
, in other words, there is no need to multiply each element ListB
by a counter, objA
as we can also simply multiply the resulting sum by this count:
return rootObj.getListA().stream()
.mapToInt(objA->objA.getListB().stream().mapToInt(ObjectB::getCount).sum()*objA.getCount())
.sum();
source to share
Pretty easy: compare ObjectA
with the sum of all yours ObjectB::getCount
multiplied by your own getCount()
, then just sum IntStream
:
int total = rootObj.getListA().stream()
.mapToInt(obja -> obja.getCount() * obja.getListB().stream().mapToInt(ObjectB::getCount).sum())
.sum();
To improve readability, you can introduce a private helper method:
int total = rootObj.getListA().stream()
.mapToInt(this::calculate)
.sum();
with a helper method:
private int calculate(ObjectA obja) {
return obja.getListB().stream()
.mapToInt(ObjectB::getCount)
.sum() * obja.getCount();
}
source to share
And for a more general solution of walking two threads at once, this is not very pleasant, but it works.
public static <A, B, C> Stream<C> zip(
Stream<A> a,
Stream<B> b,
BiFunction<A, B, C> op) {
Iterator<A> i1 = a.iterator();
Iterator<B> i2 = b.iterator();
Iterable<C> i = () -> new Iterator<C>() {
@Override
public boolean hasNext() {
return i1.hasNext() && i2.hasNext();
}
@Override
public C next() {
return op.apply(i1.next(), i2.next());
}
};
// Not certain whether we can do this in parallel - probably not.
return StreamSupport.stream(i.spliterator(), false);
}
source to share