Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compare couples of items within an ArrayList using for-each loop?

Tags:

java

for-loop

I have a vector of object and I need to compare them 1-by-1. That is:

for (Object o1 : list) {
    for (Object o2 : list) {
    //Do something with o1 and o2
    }
}

Anyway using this approach I will compare any couple twice! Using a "C" style approach, I would have done this:

for (i=0; i<n-1; i++) {
    for (j=i+1; j<n; j++) {
    //Do something with list[i] and list[j]
    }
}

where n is the length of the list.

Is there a way to do this using for-each loop?

Addition

The usage of a for-each loop is not mandatory. Anyway, I'm concerned with performances issues. Does the for-each loop is faster than a simple for accessing index directly or not?

like image 579
the_candyman Avatar asked Oct 21 '15 17:10

the_candyman


2 Answers

It is explicitly clear what your intent is with the C-like for loops - loop over every pair exactly once, so that the same pair with reversed members, e.g. (a, b) and (b, a) doesn't get processed again. That is what I would recommend; it works in Java just as well.

However, if you absolutely have to have the enhanced for loop, you can have the inner for loop operate over a sublist, with List's subList method, starting with the next element.

for (Object o1 : list) {
    List<Object> subList = list.subList(list.indexOf(o1) + 1, list.size());
    for (Object o2 : subList) {
         //Do something with o1 and o2
    }
}
like image 106
rgettman Avatar answered Sep 26 '22 12:09

rgettman


The enhanced for loop is not appropriate in all situations. If you avoid using an index, just to use indexOf in the loop, your code will be less efficient (indexOf is a linear search) and non-idiomatic.

In my opinion, the best answer is to use the explicit indices.

for (i=0; i<n-1; i++) {
    for (j=i+1; j<n; j++) {
        // do something with list.get(i) and list.get(j)
    }
}

One situation where you should avoid using get is if the List is a LinkedList, because get for a LinkedList is not a constant time operation. In this case I would do

List<Object> copy = new ArrayList<>(linkedList);
for (i=0; i<n-1; i++) {
    for (j=i+1; j<n; j++) {
        // do something with copy.get(i) and copy.get(j)
    }
}
like image 41
Paul Boddington Avatar answered Sep 23 '22 12:09

Paul Boddington