1

I'm trying to write a method that takes 2 ArrayLists of doubles and returns all the values in set1 that aren't found in set2. These numbers should be returned in set3. I keep getting an out of memory error. Can anyone point me in the right direction?

ArrayList<Double> setDiff(ArrayList<Double> set1, ArrayList<Double> set2){
    ArrayList<Double> set3 = new ArrayList<Double>();
    int count = 0;
    while(count < set1.size()){
        boolean inList = false;
        while(inList == false){
            int count2 = 0;
            while(count2 < set2.size() && set1.get(count) == set2.get(count2)){
                count2++;
            }
            if(count2 != set2.size()){
                set3.add(set1.get(count));
            }
            else{
                inList = true;
                count++;
            }
        }
    }

    return set3;
}
user2028306
  • 15
  • 1
  • 3
  • Minor note: you can write `!inList` instead of `inlist == false` (The first one is less readable, but also more common. Your choice :p) – keyser Jan 31 '13 at 22:05
  • Possible duplicate : http://stackoverflow.com/a/919420/644669 – Zakaria Jan 31 '13 at 22:05
  • Unfortunately I cannot use .contains() or .remove() because of the specifications of the assignment. – user2028306 Jan 31 '13 at 22:05
  • possible duplicate of [How can I calculate the difference between two ArrayLists?](http://stackoverflow.com/questions/919387/how-can-i-calculate-the-difference-between-two-arraylists) – Zakaria Jan 31 '13 at 22:06
  • Then replace contains() with a loop (see Gothmog's answer below). – keyser Jan 31 '13 at 22:06

3 Answers3

2

I would recommend using Collection utils Disjunction

Returns a Collection containing the exclusive disjunction (symmetric difference) of the given Collections.

The cardinality of each element e in the returned Collection will be equal to max(cardinality(e,a),cardinality(e,b)) - min(cardinality(e,a),cardinality(e,b)).

This is equivalent to subtract(union(a,b),intersection(a,b)) or union(subtract(a,b),subtract(b,a)).

Woot4Moo
  • 23,987
  • 16
  • 94
  • 151
2

Some loop is likely not stopping as you would expect.

The following code snippet would accomplish pretty much the same you are trying to do.

for (Double d : set1) {
    if (!set2.contains(d)) {
        set3.add(d);
    }
}

UPDATE: since you say you cannot use contains(), you can perform the checks by yourself:

for (Double d : set1) {
        boolean found = false;
        for (int i=0; i<set2.size() && !found; i++) {
                if (d.equals(set2.get(i))) {
                    found = true;
            }
        }
        if (!found) {
            set3.add(d);
        }
}

EDIT: Furthermore, the problem in your code lies in the line

  if(count2 != set2.size()){

You should change != with >, since in the case of being count2 less than set2, the external count variable will not increase, resulting in an infinite loop, and after a few seconds, an OutOfMemoryError.

Also, your algorithm wasn't 100% correct either, since the looping through the second list was not consistent. You can see a similar approach with while-loops below:

                int count = 0;
                while (count < set1.size()) {
                    boolean inList = false;
                    int count2 = 0;
                    while (inList == false && count2 < set2.size()) {
                        if (set1.get(count).equals(set2.get(count2))) {
                            inList = true;
                        }
                        count2++;
                    }
                    if (!inList) {
                            set3.add(set1.get(count));
                    }
                    count++;
               }
Gothmog
  • 871
  • 1
  • 8
  • 20
2

it may be advantageous to sort your lists before doing these comaprisons, then searching for items can be performed much more efficiently.

you can also try doing this:

set1.removeAll(set2)

items remaining in set1 were the items not in set2

Peter Elliott
  • 3,273
  • 16
  • 30