3

I have the following code which I use a lot of times in the class.

for (int i = 0; i < someList.size(); i++) {
    for (int j = 0; j < someList.size(); j++) {
        if (i != j) {
            someList.get(i).sendMessageTo(someList.get(j))); //variable action
        }
    }
}

The purpose of the loop is to make each element in the List to send a message (or perform another action) to every element in the list except itself.

Is there any way I can create a helper method so I don't have to repeat the loop code.

Edit: I need just one helper method to take care of the for loop and the if algorithm. I will supply the List and the whatever action I need to use. It should work for all.

I want to be able to state the variable action and call the helper method.

Thanks.

1
  • A really bad way to do this might be to use enums for another layer of indirection (and I'm not even 100% sure that would work), but I feel there's gotta be a better way... Commented Jun 11, 2014 at 21:25

3 Answers 3

2

You could do something like (I don't know what type is in your List, I called it Element):

public interface ApplySomeAction
{
    public apply(Element e1, Element e2);
}

...

public void applyActionToAllElements(ApplySomeAction action)
{
    for (int i = 0; i < someList.size(); i++) {
       for (int j = 0; j < someList.size(); j++) {
           if (i != j) {
               action.apply(someList.get(i), someList.get(j));
           }
       }
    }
}

later call it with:

applyActionToAllElements(new ApplySomeAction() {
    public apply(Element e1, Element e2)
    {
        e1.sendMessageTo(e2));
    }
};

Could make another interface+method with just one element if you often do an action with just one of those elements.

Sign up to request clarification or add additional context in comments.

2 Comments

do happens to be a reserved word; usually apply is picked instead.
If you rename that do to say doer also update the call to doer.apply(...). In Java 8, you can use a closure instead.
0

You could maybe get rid of one of the loops by doing it this way:

for (int i = 0; i < someList.size() - 1; i++) {
    someList.get(i).sendMessageTo(someList.get(i + 1))); //variable action
}

And use @NESPowerGlove's solution to abstract the method that's called.

Comments

0

I'd make me an Iterable

/**
 * Returns all pairs of the list except those where i == j.
 * @param <T> 
 */
public class AllPairs<T> implements Iterable<Pair<T, T>> {
    // The list.
    private final List<T> list;

    public AllPairs(List<T> list) {
        this.list = list;
    }

    @Override
    public Iterator<Pair<T, T>> iterator() {
        return new PairIterator();
    }

    private class PairIterator implements Iterator<Pair<T, T>> {
        // The indexes.
        int i = 0;
        int j = 0;
        // The next to return.
        Pair<T, T> next = null;
        // Easier to read.
        int size = list.size();

        @Override
        public boolean hasNext() {
            while (next == null && (i < size || j < size)) {
                // Step j.
                j += 1;
                // Wrap j.
                if (j >= size && i < size) {
                    j = 0;
                    i += 1;
                }
                if (i < size && j < size && j != i) {
                    // Grab it.
                    next = new Pair<>(list.get(i), list.get(j));
                }
            }
            return next != null;
        }

        @Override
        public Pair<T, T> next() {
            Pair<T, T> it = next;
            next = null;
            return it;
        }
    }

}

/**
 * A simple Pair
 */
public static class Pair<P, Q> {

    public final P p;
    public final Q q;

    public Pair(P p, Q q) {
        this.p = p;
        this.q = q;
    }
}

public void test() {
    System.out.println("Hello");
    List<Integer> l = Arrays.asList(0, 1, 2, 3);
    for (Pair<Integer, Integer> p : new AllPairs<>(l)) {
        System.out.println("[" + p.p + "," + p.q + "]");
    }
}

Then define an interaction mechanism - this would be almost trivial using Lambdas:

// Objects that can interact with each other.
public interface Interacts<T extends Interacts<T>> {

    public void interact(T with);
}

public static <T extends Interacts<T>> void interactAllPairs(List<T> l) {
    // Interact all pairs.
    for (Pair<T, T> p : new AllPairs<>(l)) {
        p.p.interact(p.q);
    }
}

Then you can make your message objects interact - here's a simple example:

// Interact by sending a message.
public class Messenger implements Interacts<Messenger> {

    private final int me;

    public Messenger(int me) {
        this.me = me;
    }

    @Override
    public void interact(Messenger with) {
        sendMessage(with);
    }

    public void sendMessage(Messenger to) {
        System.out.println(this + "->" + to);
    }

    @Override
    public String toString() {
        return Integer.toString(me);
    }
}

Testing now looks like:

public void test() {
    // Meassage list.
    List<Messenger> messages = new ArrayList<>();
    for (int i = 0; i < 4; i++) {
        messages.add(new Messenger(i));
    }
    interactAllPairs(messages);
}

giving your required output:

0->1
0->2
0->3
1->0
1->2
1->3
2->0
2->1
2->3
3->0
3->1
3->2

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.