Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compare equality of lists of arrays with modern Java?

I have two lists of arrays.

How do I easily compare equality of these with Java 8 and its features, without using external libraries? I am looking for a "better" (higher-level, shorter, more efficient) solution than brute-force code like this (untested code, may contain typos etc, not the point of the question):

boolean compare(List<String[]> list1, List<String[]> list2)  {     // tests for nulls etc omitted     if(list1.size() != list2.size()) {        return false;     }     for(i=0; i<list1.size(); ++i) {         if(!Arrays.equals(list1.get(i), list2.get(i))) {             return false;         }     }     return true; } 

Or, if there isn't any nicer way, that's a valid answer too.

Bonus: If Java 9 offers an even better way what whaterver Java 8 can offer, feel free to mention it as well.

Edit: After looking at the comments, and seeing how this question has become moderately hot, I think the "better" should include first checking lengths of all arrays, before checking array contents, because that has potential to find inequality much quicker, if inner arrays are long.

like image 773
hyde Avatar asked Feb 15 '16 11:02

hyde


People also ask

Can we use == to compare arrays in Java?

Java Arrays class provides the equals() method to compare two arrays. It iterates over each value of an array and compares the elements using the equals() method.

How do I compare two lists in Java?

Java provides a method for comparing two Array List. The ArrayList. equals() is the method used for comparing two Array List. It compares the Array lists as, both Array lists should have the same size, and all corresponding pairs of elements in the two Array lists are equal.


2 Answers

The for loop at least can be streamified, leading to:

return (list1.size()==list2.size() &&         IntStream.range(0, list1.size())                  .allMatch(i -> Arrays.equals(list1.get(i), list2.get(i))); 
like image 118
khelwood Avatar answered Sep 29 '22 12:09

khelwood


1) Solution based on Java 8 streams:

List<List<String>> first = list1.stream().map(Arrays::asList).collect(toList()); List<List<String>> second = list2.stream().map(Arrays::asList).collect(toList()); return first.equals(second); 

2) Much simpler solution (works in Java 5+):

return Arrays.deepEquals(list1.toArray(), list2.toArray()); 

3) Regarding your new requirement (to check the contained String arrays length first), you could write a generic helper method that does equality check for transformed lists:

<T, U> boolean equal(List<T> list1, List<T> list2, Function<T, U> mapper) {     List<U> first = list1.stream().map(mapper).collect(toList());     List<U> second = list2.stream().map(mapper).collect(toList());     return first.equals(second); } 

Then the solution could be:

return equal(list1, list2, s -> s.length)     && equal(list1, list2, Arrays::asList); 
like image 42
Dragan Bozanovic Avatar answered Sep 29 '22 12:09

Dragan Bozanovic