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.

Answers 1

  • 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);
    

Sorry, you do not have a permission to answer to this question.