I have the following code:
IntStream.range(0, width).forEach(x1 -> {
IntStream.range(0, height).forEach(y1 -> {
IntStream.rangeClosed(x1-1, x1+1).forEach(x2 -> {
IntStream.rangeClosed(y1-1, y1+1).forEach(y2 -> {
if ((x1 != x2 || y1 != y2) && getNode(x2, y2) != null){
getNode(x1, y1).registerObserverAtNeighbor(getNode(x2, y2));
}
});
});
});
});
Is there a way to write the above using fewer nested statements? It's basically "for each node from (0,0) to (width,height) register observer at nodes from (x-1,y-1) to (x+1,y+1), but not at self".
What you have is basically 4 nested loops. It makes sense because you are iterating over two dimensions of a matrix, and then, for each node, you iterate over a small matrix that consists of its neighbourgs.
Something like this.
I guess you could use a recursive function just for the syntax, although no benefit really.
In principle, you can replace nested loops with a
Stream
usingflatMap
. This requires that you choose an element type capable of holding the information equivalent to the loop variables, if you need it. In your case, it’s the two values forx
andy
. It would simplify the code if yourNode
class holds these information as you can easily iterate over nodes rather thanint
values then. Since you didn’t specify the capabilities of yourNode
class, here is an example which uses along[]
of size two to hold the points:It still simplifies the innermost code by moving code to the outside, where possible, e.g. the
getNode
calls. You can also simplify the code by putting the repeated task of creating aStream
over points for an area into a method:Then you can use it like this:
It still could be easier if you have/use a dedicated point class or if the node class holds the point information (and has a comparison method for it, in the best case).
Since you operate on nodes I suggest to create streams of nodes in the first place. Please note that I'm making some assumptions about the nodes.
Creating a stream using your approach: