Every Java collection implements the equals() method, which compares it with another collection. In the case of List, two lists are considered equal (the method list1.equals(list2) returns true) when:
- Each collection is of type List
- Each element of one list is equal to the element of another list in the same position
Here is the code that illustrates it:
List<String> list1 = new ArrayList<>();
list1.add("s1");
list1.add("s2");
List<String> list2 = new ArrayList<>();
list2.add("s1");
list2.add("s2");
System.out.println(list1.equals(list2)); //prints: true
list2.sort(Comparator.reverseOrder());
System.out.println(list2); //prints: [s2, s1]
System.out.println(list1.equals(list2)); //prints: false
If two lists are equal, their hashCode() methods return the same integer value. But the equality of hashCode() results does not guarantee that the lists are equal. We will talk about the reason for that while discussing the hashCode() method implementation for the elements of the Set collection in the next section.
The containsAll(Collection) method of the List interface (or any collection that implements the Collection interface) returns true only if all elements of the provided collection are present in the list. If the size of the list and the size of the provided collection are equal, we can be sure that the same (well, equal) elements compose each of the compared collections. It does not guarantee though that the elements are of the same type, because they might be children of different generations with the equals() method implemented only in the common parent.
If not, we can find the difference using the methods retainAll(Collection) and removeAll(Collection), described earlier in this section. Let's assume we have two lists as follows:
List<String> list1 = new ArrayList<>();
list1.add("s1");
list1.add("s1");
list1.add("s2");
list1.add("s3");
list1.add("s4");
List<String> list2 = new ArrayList<>();
list2.add("s1");
list2.add("s2");
list2.add("s2");
list2.add("s5");
We can find which elements in one list are not present in the other:
List<String> list = new ArrayList<>(list1);
list.removeAll(list2);
System.out.println(list); //prints: [s3, s4]
list = new ArrayList<>(list2);
list.removeAll(list1);
System.out.println(list); //prints: [s5]
Notice how we have created a temporary list to avoid corruption of the original one.
But this difference does not tell us about possibly duplicate elements present in each of the list. To find it, we can use the retainAll(Collection) method:
List<String> list = new ArrayList<>(list1);
list.retainAll(list2);
System.out.println(list); //prints: [s1, s1, s2]
list = new ArrayList<>(list2);
list.retainAll(list1);
System.out.println(list); //prints: [s1, s2, s2]
Now we have the full picture of the differences between the two lists.
Also, please, notice that the retainAll(Collection) method can be used to identify the elements that belong to each of the lists.
But neither retainAll(Collection) nor removeAll(Collection) guarantee that the compared list and the collection passed in contain elements of the same type. They might be a mix of children with a common parent that have the equals() method implemented in the parent only, and the parent type is the type of the list and the collection passed in.