Reuse code for looping through multidimensional-array
Asked Answered
S

3

2

Let's say I have a multi-dimensional array as a member of a class and a lot of methods, that loop through every element of the array and then operate on it. The code might look like this:

public class Baz {

    private Foo[][] fooArray = new Foo[100][100];

    public Baz() {
        for (int i = 0; i < fooArray.length; i++) {
            for (int j = 0; j < fooArray[i].length; j++) {
                // Initialize fooArray
            }
        }
    }

    public void method1() {
        for (int i = 0; i < fooArray.length; i++) {
            for (int j = 0; j < fooArray[i].length; j++) {
                // Do something with fooArray[i][j] 
            }
        }
    }

    public void method2() {
        for (int i = 0; i < fooArray.length; i++) {
            for (int j = 0; j < fooArray[i].length; j++) {
                // Do something else with fooArray[i][j] 
            }
        }
    }

    // and so on
}

Now, since the code for the loop is always the same, only the operation within the loop changes, is there any way the code for looping could be somehow refactored into a seperate method? It would be so nice to be able to do

doInLoop(functionToExecute());

What would be the nearest substitute for doing something like this, if it is even possible?

Serum answered 31/7, 2013 at 14:40 Comment(0)
V
6

What you are looking for is the Command pattern: define a single-method interface and implement it for each use case as an anonymous class. You'll pass an instance of this interface to a method which does all the boilerplate and calls your method just for the interesting part:

public void forAllMembers(Foo[][] fooArray, Command c) {
    for (int i = 0; i < fooArray.length; i++) {
        for (int j = 0; j < fooArray[i].length; j++) {
            c.execute(fooArray[i][j]);
        }
    }
}

Or, wait for Java 8, which will introduce Lambdas and will give your problem a first-class solution!

Vanderhoek answered 31/7, 2013 at 14:45 Comment(3)
@Skippy I'm not familiar with drivers in python, but I'm quite sure that this use case would be covered by generators and the inversion of control they offer.Vanderhoek
@Skippy In every modern language except Java, lambda functions and closures are a staple feature.Vanderhoek
@Skippy No, C is not being phased out at all. What has happened is that its scope has narrowed to only the low-level routines. But it's not facing any opposition in that domain, and this is likely going to stay that way for at least a decade.Vanderhoek
G
2

You could sth like this:

public void method1(Performer p) {
    for (int i = 0; i < fooArray.length; i++) {
        for (int j = 0; j < fooArray[i].length; j++) {
            p.doIt(fooArray[i][j]);
        }
    }
}


static interface Performer {

    public void doIt(int ij);
}

then implement different performers and pass them to this single method.

This approach is called Command Pattern

Gyasi answered 31/7, 2013 at 14:44 Comment(0)
N
2
public Baz() {
    for (int i = 0; i < fooArray.length; i++) {
        for (int j = 0; j < fooArray[i].length; j++) {
            fooArray[i][j] = initArray(/* .. */);
            doSomethingWithFooArray(fooArray[i][j] );
            doSomethingElseWithFooArray(fooArray[i][j] );
        }
    }
}

If you would like to create something generic you can use Interface,

public interface FooItf{
   public void doSomethingWithFooArray(int value );
   public void doSomethingElseWithFooArray(int value );
   public int initArray(/* .. */);
 } 

and now you can write something:

 public looping(FooItf foo) {
    for (int i = 0; i < fooArray.length; i++) {
        for (int j = 0; j < fooArray[i].length; j++) {
            fooArray[i][j] = foo.initArray(/* .. */);
            foo.doSomethingWithFooArray(fooArray[i][j] );
            foo.doSomethingElseWithFooArray(fooArray[i][j] );
        }
    }
}

For now you can generate several classes based on FooItf and implement any internal logic.

Ne answered 31/7, 2013 at 14:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.