Reputation: 356
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.
Upvotes: 3
Views: 255
Reputation: 65813
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
Upvotes: 0
Reputation: 5496
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.
Upvotes: 2
Reputation: 7459
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.
Upvotes: 0