24

I'm having trouble with what I thought should be a pretty simple problem.

I need to compare every item in an arrayList with every other item in the the list without comparing items to themselves. It's not as simple as calling an equals() comparison, it involves some custom logic that I've omitted from my code below. Also the ArrayList should not be changed in any way.

The problem I seem to be having is that once I get into the second loop, I don't know if I have another object to compare to (since its a variable sized list).

for(int i =0; i< list.size(); i++){ 
    //get first object to compare to
    String a = list.get(i).getA();

    Iterator itr = list.listIterator(i + 1 ); // I don't know if i + 1 is valid
    while(itr.hasNext()){
        // compare A to all remaining items on list
    }
}

I think I probably going about this the wrong way, I'm open to suggestions or tips on how to do this better.

Zangdak
  • 242
  • 4
  • 22
JavaKungFu
  • 1,264
  • 2
  • 11
  • 24
  • You say that the ArrayList should not be changed in any way, so the size of the list is not variable : it's constant. And i+1 will thus be a valid index for listIterator(), since i is guaranteed to be < list.size() and listIterator accepts an index up to list.size() inclusive. Your code (once trivial syntax errors are fixed), should thus run as is. – JB Nizet Feb 14 '11 at 15:45
  • Awesome, this question helped me tremendously! – sdot257 Feb 14 '11 at 20:09
  • Over at [CR](https://codereview.stackexchange.com/), this might fit the _Not As Easy As It Looks_ category (especially with a non-symmetric `compare` and general `java.util.List<>`. Starting with `compare every item in [a List L] with every other item in [L]` – greybeard Jan 11 '16 at 05:47

8 Answers8

49
for (int i = 0; i < list.size(); i++) {
  for (int j = i+1; j < list.size(); j++) {
    // compare list.get(i) and list.get(j)
  }
}
Kaleb Brasee
  • 51,193
  • 8
  • 108
  • 113
3

What's the problem with using for loop inside, just like outside?

for (int j = i + 1; j < list.size(); ++j) {
    ...
}

In general, since Java 5, I used iterators only once or twice.

Nikita Rybak
  • 67,365
  • 22
  • 157
  • 181
  • 1
    You should read Effective Java item 46, it explicitly recommends against traditional for loops (whenever possible) – Sean Patrick Floyd Feb 14 '11 at 16:08
  • @Sean Patrick Floyd, JVM can use intrinsic for that, if need be. I dont say at the moment it does use but the iterator is the easiest thing to be optimized away (via escape analysis) – bestsss Feb 14 '11 at 17:03
  • 2
    @bestsss I'm not talking about effective byte code (and neither is Josh Bloch, in this case), but about readable and non-error-prone source code – Sean Patrick Floyd Feb 14 '11 at 17:07
2

In some cases this is the best way because your code may have change something and j=i+1 won't check that.

for (int i = 0; i < list.size(); i++){  
    for (int j = 0; j < list.size(); j++) {
                if(i == j) {
               //to do code here
                    continue;
                }

}

}

Tariq Mahmood
  • 147
  • 15
Piotr Jankowski
  • 146
  • 1
  • 8
  • _One_ interpretation of `compare every item in [a List L] with every other item in [L]`. It might be about time to ponder/present a `java.util.stream`-based approach - pity Stream is obliged to be cloneable and provide a useful `equals()` just as much as Iterator. – greybeard Jan 11 '16 at 06:04
2

This code helped me get this behaviour: With a list a,b,c, I should get compared ab, ac and bc, but any other pair would be excess / not needed.

import java.util.*;
import static java.lang.System.out;

// rl = rawList; lr = listReversed
ArrayList<String> rl = new ArrayList<String>();
ArrayList<String> lr = new ArrayList<String>();
rl.add("a");
rl.add("b");
rl.add("c");
rl.add("d");
rl.add("e");
rl.add("f");

lr.addAll(rl);
Collections.reverse(lr);

for (String itemA : rl) {
    lr.remove(lr.size()-1);
        for (String itemZ : lr) {
        System.out.println(itemA + itemZ);
    }
}

The loop goes as like in this picture: Triangular comparison visual example

or as this:

   |   f    e    d    c    b   a
   ------------------------------
a  |  af   ae   ad   ac   ab   ·
b  |  bf   be   bd   bc   ·   
c  |  cf   ce   cd   ·      
d  |  df   de   ·         
e  |  ef   ·            
f  |  ·               

total comparisons is a triangular number (n * n-1)/2

BrnLng
  • 21
  • 2
0

The following code will compare each item with other list of items using contains() method.Length of for loop must be bigger size() of bigger list then only it will compare all the values of both list.

List<String> str = new ArrayList<String>();
str.add("first");
str.add("second");
str.add("third");
List<String> str1 = new ArrayList<String>();
str1.add("first");
str1.add("second");
str1.add("third1");
for (int i = 0; i<str1.size(); i++)
{
System.out.println(str.contains(str1.get(i)));
}

Output is true true false

Karthick
  • 21
  • 1
  • 4
0

You can do it like this.

for (int i = 0; i < arrayList.size(); i++) {
    for (int j = 0; j < arrayList.size(); j++) {
        if (i!=j &&  arrayList.get(i).YourObjectItem().equals(arrayList.get(j).YourObjectItem())) {
            //Your code will be here
        }

    }
}
Reza Rahemtola
  • 1,182
  • 7
  • 16
  • 30
0

Old question, but I just wanted to provide a functional version from the Kaleb Brasee's one, (which, BTF is far more faster and heap friendly than this) for functional programming purists.

    IntStream.range(0, list.size())
        .forEach(i -> compare(list.get(i),
                               list.subList(i + 1, list.size())));
...

private void compare(final Element element, final List<Element> list) {

    list.stream()
        //whatever 

}
spekdrum
  • 1,559
  • 2
  • 11
  • 15
0
Arraylist<String> list =new Arraylist<>();
list.add("water");
list.add("air");
list.add("earth");
list.add("water");

Set<String> set = new LinkedHashSet<>();
      set.addAll(list);
    System.out.println(set.toString())