Write Once Use Everywhere: Multidimensional array traversal
where individual cells reside in an n x n region, and those regions
  reside in an n x n area


First problem, there are no Area or Region or Cell in the code provided.


  I need to be able to address both the regions and the individual cells
  within the regions separately.


Then you should have written something like 

class Area {
    Region getRegion(int row, int col);
}

class Region {
    Cell getCell(int row, int coll);
}

class Cell {

}



  so I could write it once and use it everywhere:


Then you should write something composable. void exec(...) is not very composable; because it returns void it can't be pipelined. Extract Streams (or methods returning a value), and keep Consumers (or methods returning void) simple.

For example if your utility method traverseDoubleRowMajor were something like :

Stream&lt;Cell&gt; cellsOf(Area area)


instead of :

TraversalUtil.traverseDoubleRowMajor( (i, j, k, m) -&gt; {
    System.out.println(getCellAt(i, j, k, m)); // or whatever
});


you could then simply do :

 cellsOf(area).forEach(System.out::println);


So how could you write a cellsOfRegion? It'd be easy if you'd first made areas and regions etc explicit as I've shown above:

private static Stream&lt;Cell&gt; cellsOf(Area area) {
    return gridElements(BOUND, BOUND, area::getRegion)
            .flatMap(region -&gt; gridElements(BOUND, BOUND, region::getCell));
}

private static &lt;R&gt; Stream&lt;R&gt; gridElements(int maxRow, int maxCol, BiFunction&lt;Integer, Integer, R&gt; f) {
    return IntStream.range(0, maxRow).boxed().flatMap(row -&gt; (
            IntStream.range(0, maxCol).boxed().map(col -&gt; f.apply(row, col))));
}


EDIT


  For low iterations, how big is the performance hit for setting up the
  pipeline for a steam?


Short answer, you should try for yourself. Longer prediction: In almost all cases IO dominates anyway. Where IO is not involved memory access should dominate. And a pipeline using streams should be faster than a pipeline that puts the intermediate results in collections.

List&lt;A&gt; inputElements = elementsOf(input);
List&lt;A&gt; result1 = pipelineStep1(inputElements);
List&lt;A&gt; result2 = pipelineStep2(result1);
// etc etc...
B resultN = pipelineStepN(resultNMinusOne);


should be slower than 

B result = elementsOf(input)
    .filter(pipelineStep1)
    .flatMap(pipelineStep2)
    // etc etc...
    .collect(pipelineStepN);



  And second, is there a way to achieve different traversal orders (i.e.
  not just row major)?


Sure, one solution would be:

private static &lt;R&gt; Stream&lt;R&gt; colMajor(int maxRow, int maxCol, BiFunction&lt;Integer, Integer, R&gt; f) {
    return IntStream.range(0, maxCol).boxed().flatMap(col -&gt; (
            IntStream.range(0, maxRow).boxed().map(row -&gt; f.apply(row, col))));
}


Or with less repetition just 

private static &lt;R&gt; Stream&lt;R&gt; colMajor(int maxRow, int maxCol, BiFunction&lt;Integer, Integer, R&gt; f) {
    return gridElements(maxCol, maxRow, (col, row) -&gt; f.apply(row, col);
}


If you do this you may consider renaming method and parameter names accordingly. e.g. instead of names like row and col in gridElements, which you now would be using for both row-major and col-major traversal; canonical names for integer function parameters/loop counters i, j or m, n etc.