Zizheng Tai Zizheng Tai - 13 days ago 6
Python Question

Blocking nested-loops iterator

I'm trying to port the following Python generator to a Java

Iterator
:

def gen_sums(blocks1, blocks2):
for b1 in blocks1:
for b2 in blocks2:
for n1 in b1:
for n2 in b2:
yield n1 + n2


In the Java version, the interfaces look like:

public class Block {
...

public Iterator<Integer> iterator() { ... }
}

public class GenSums implements Iterator<Integer> {
private Iterator<Block> blocks1;
private Iterator<Block> blocks2;

...

@Override
public boolean hasNext() { /* TODO */ }

@Override
public Integer next() { /* TODO */ }
}


...which I've found extremely hard to get right. There are simply a lot of states to store in the
GenSums
class, and to resume from. Is there any "standard" way to implement this kind of iterators in Java? I'd like to avoid using third-party libraries.

Answer

If you are using Java 8 then you might want to consider producing a stream rather than an iterator. A stream can be converted into an iterator if required (using BaseStream.iterator()).

So, for example:

class Block {
    private final int[] b;

    public IntStream getBs() {
        return Arrays.stream(b);
    }
}

public IntStream generate(List<Block> block1, List<Block> block2) {
    return block1.stream()
        .flatMapToInt(b1 -> block2.stream()
            .flatMapToInt(b2 -> b1.getBs()
                .flatMap(n1 -> b2.getBs().map(n2 -> n1 + n2)));
}

As you can see that is pretty close to the equivalent in Python - the for statements become flatMap and the yield becomes a map.

Comments