3

My question is that I am going to compare two arraylists in Java

e.g

String prop1 = "String"
String prop2 = "OtherString"
MyObject obj1 = new MyObject(prop1,prop2);
MyObject obj2 = new MyObject(prop1,prop2);
MyObject obj3= new MyObject(prop1,prop2);

ArrayList<MyObject> array1 = new Arraylist<>();
ArrayList<MyObject> array2 = new Arraylist<>();
//array 1 has 3 objects
array1.add(obj1);array1.add(obj2);array1.add(obj3);
//array 2 has 2 objects
array2.add(obj1);array2.add(obj2);

With a comparison method i know these arrays are different

(My method returns false if the arrays have the same elements even if they are not in the same order, and true if they have the same elements)

So, the method is going to return FALSE

My question is:

if(!methodToCompareArrays(array1,array2)){
    //HOW TO GET THE DIFFERENT objects (IN THIS CASE, obj3 is the different object)
    //this is the question :)
}else{
    //If there is no difference, well, it doesn't matter too much

Notice that I'm going to have multiple objects into these arraylists, and also the method efficiency is important (not crucial, but important at least). I've seen the answers here But I'm not sure which one would be better or worst

Thanks in advance.

Community
  • 1
  • 1
mgXD-2
  • 102
  • 7
  • 1
    Doesn't `methodToCompareArrays` already do at least some of this for you? – Scott Hunter Sep 25 '14 at 19:19
  • 1
    Seems to me Symmetric Difference is what you are looking... take a look at Apache Commons CollectionUtil `disjunction` function – gtgaxiola Sep 25 '14 at 19:20
  • it first compares arraylists sizes, so it will return false in this case. My method is based on DiddiZ' answer [here](http://stackoverflow.com/questions/13501142/java-arraylist-how-can-i-tell-if-two-lists-are-equal-order-not-mattering) – mgXD-2 Sep 25 '14 at 19:23
  • What should the answer be for (array1, array2), vs. what should it be for (array2, array1)? There can be **different** objects in both sets (i.e. objects present in one that aren't in the other); what exactly are you looking for in that case? – Tim Sep 25 '14 at 19:33
  • in both cases, the answer should be "object3", and probably yes(objects present in one that aren't in the other) , but it is more likely to be that one array has all the objects and the other array has all the objects except three or five. – mgXD-2 Sep 25 '14 at 19:58

3 Answers3

1

If the objects in these lists aren't important for you, you can do something like:

array1.removeAll(array2);

This will remove from array1, all the elements that exist in array2.

So if array1 = [obj1, obj2, obj3] and array2 = [obj1, obj2]

After the removeAll:

array1 = [obj3] and array2 = [obj1, obj2]

If you cannot remove the objects from either list then make a temp List and remove from there to get extra object.

Rahul Dabas
  • 726
  • 2
  • 15
  • 27
  • With the OP's new info about wanting a collection of all elements that are in either one but not the other, you'll need to update your answer to account for anything in array2 that's not in array1. And you won't be able to do this in-place anymore... – Tim Sep 25 '14 at 20:16
1

You should probably use java's set interfaces for this.

Now, one thing that's going to be important is having a good equals method on MyObject to be able to compare whether two MyObjects are the same.

Then you could use that documentation link above to check the intersection of two sets. If the items that are in both sets are the same number of items as in one set, then they're the same set (irrespective of order).

HashSet<MyObject> set1 = new HashSet<MyObject>(array1);
HashSet<MyObject> set2 = new HashSet<MyObject>(array2);

Set<MyObject> intersection = new HashSet<MyObject>(set1);
intersection.retainAll(set2);

if(intersection.size() == set2.size()) { 
    // They're the same.
} else { 
    HashSet<MyObject> itemsOnlyInSet1 = intersection;
    HashSet<MyObject> itemsOnlyInSet2 = set2.retainAll(set1);
} 
FrobberOfBits
  • 17,634
  • 4
  • 52
  • 86
  • If the OP is already going to have ArrayLists, I'm not sure it's worth creating Sets from each just to do this comparison. It would be worth it if there were going to be lots of items (thousands? tens or hundreds of thousands? I'm not sure), but that doesn't sound like the scale based on the OP's description... – Tim Sep 25 '14 at 19:41
  • 1
    I don't understand too much if I should replace "Type" with "MyObject" (maybe this comment is noobish). @Tim well, I don't expect thousands, maybe one hundred or less. – mgXD-2 Sep 25 '14 at 19:54
  • For sets of one hundred or less, using this approach (Sets) should be just fine. @Tim is right that this might not be the best approach if the number of items is really huge, but less than a hundred isn't really huge. Besides, sets have the advantage of de-duplicating; an array list lets you stuff more than one of the same item into the array. Take these arrays: {1, 2, 2, 3} and {1, 3}. The items in the left list that aren't in the right should be {2}, not {2, 2}. That's sets for you rather than lists. – FrobberOfBits Sep 25 '14 at 20:04
  • Oh, and OP -- yes I updated the answer. My use of Type was wrong. Should have been MyObject. – FrobberOfBits Sep 25 '14 at 20:06
  • 1
    I was actually saying the opposite: finding the disjunction of two HashSets will be more efficient than finding the disjunction of two ArrayLists (N log N versus N^2), so FrobberOfBits's suggestion becomes a better option as the number of elements goes up. But N needs to be relatively large before you'd actually see a difference in practice, and creating a new HashSet from each ArrayList just to get a small improvement isn't worth it because there's a cost to making the new HashSets and then garbage collecting them. But it's worth it for very large N... – Tim Sep 25 '14 at 20:09
  • This is a common SO thing - my answer is intended to teach about sets and intersection; if you layer on the additional criteria that it must be the fastest or most efficient solution, then it would be usual that the clearest most simple solution is not the right one, right? Following the injunction against premature optimization, and given the fact that n is quite small, I'd argue it doesn't much matter. (But I'd reserve the right to change my mind if OP says he's going to do this in a tight loop 80 billion times) – FrobberOfBits Sep 25 '14 at 20:14
-2

I am not sure I understand what your question is but if you are trying to compare and sort list of objects, the best option is to look up TreeMaps from the Collections API. Try this:

Difference between HashMap, LinkedHashMap and TreeMap

Community
  • 1
  • 1
SammarZ
  • 11
  • 3
  • I don't see any reference to sorting in the OP's post, nor to anything that would require a Map as opposed to a simple collection of elements... – Tim Sep 25 '14 at 19:35
  • I never said there's a reference to 'sorting'. Please read what I wrote again. I guessed that because he wanted to compare a list of objects he might be interested in sorting them. I think there was not anything in my post to downvote it. – SammarZ Sep 25 '14 at 19:42
  • Also, he seems to have two fields 'prop1' and 'prop2'. If he's implemented his comparison method by comparing one of these fields then he might as well look into maps that use a key-value pair. He could then use his comparison field as the key in the map. – SammarZ Sep 25 '14 at 19:46