Asserting Java Lists for Equality Ignoring the Order

Demonstrates different ways of asserting if two Lists in Java have the same elements irrespective of the order.

Overview

Java List is an ordered collection of elements, so we use List implementation to retain the order of the elements in it.

In Java, and especially during Unit Testing, we need to test if a List has particular elements ignoring their order. Given the ordered nature of Lists, there is no straightforward way in Java to assert the List’s equality ignoring the order.
This tutorial covers ways to verify if two Java List instances have the same elements in whatever order.

Using TestNG and JUnit

Neither TestNG nor JUnit provides any direct means of verifying if two Lists have the same elements, irrespective of their order. We can, however, derive an assertion manually.

Example of asserting two Lists are equal using TestNG and JUnit.

List<Integer> list1 = List.of(11, 12, 13, 14, 16);
List<Integer> list2 = List.of(14, 13, 12, 16, 11);

Assert.assertTrue(
    list1.size() == list2.size() &&
    list1.containsAll(list2) &&
    list2.containsAll(list1)
);Code language: Java (java)

This assertion will only pass if the first List has all the elements of the second List and vice versa, and both lists contain the same number of elements.

Using the same assertion to compare our first and the third List will fail because they have a different number of elements. Thus, we will reverse the statement.

List<Integer> list1 = List.of(11, 12, 13, 14, 16);
List<Integer> list3 = List.of(11, 12, 13, 14, 16, 12);

Assert.assertFalse(
    list1.size() == list3.size() &&
    list1.containsAll(list3) &&
    list3.containsAll(list1)
);Code language: Java (java)

Using AssertJ

The AssertJ Assertion provides the containsExactlyInAnyOrderElementsOf() method that verifies if two Lists have the same elements ignoring their order.

Let’s see an example of using AssertJ to compare two lists of the same elements and size.

List<Integer> list1 = List.of(11, 12, 13, 14, 16);
List<Integer> list2 = List.of(14, 13, 12, 16, 11);

Assertions.assertThat(list1)
    .containsExactlyInAnyOrderElementsOf(list2);Code language: Java (java)

Both lists had precisely the same elements and the exact size; hence the AssertJ assertion succeeds.

This assertion, however, fails when we have two Java Lists containing the same elements but differentiating in size. That means the containsExactlyInAnyOrderElementsOf() fails when one of the Lists has duplicate elements.

The following two Java Lists have exactly the same elements; however, the second List has a duplicate element. Thus, the following assertion will fail.

List<Integer> list1 = List.of(11, 12, 13, 14, 16);
List<Integer> list3 = List.of(11, 12, 13, 14, 16, 12);

Assertions.assertThat(list1)
    .containsExactlyInAnyOrderElementsOf(list3);
//failsCode language: Java (java)

To assert if two Java Lists are equal in order-agnostic and size-agnostic ways, we can use the hasSameElementsAs() assertion.

Assertions.assertThat(list1)
    .hasSameElementsAs(list3);Code language: Java (java)

The assertion verifies if the two Java Lists have the same elements ignoring their order and duplicates.

Using Hamcrest

If we wish to use the Hamcrest framework for Unit Testing, we can assert the equality of two Java Lists irrespective of their order, as shown in the following snippet.

MatcherAssert.assertThat(list2, 
    Matchers.containsInAnyOrder(list2.toArray()));Code language: Java (java)

The containsInAnyOrder() creates a matcher to verify if two iterables have the same elements and size, ignoring the order of the elements.

The Assertion order-agnostic matcher verifies if the two Lists have the exact duplicates. Thus, the following assertion that compares two Lists of the same elements but different duplicates fails.

MatcherAssert.assertThat(list2, 
    Matchers.containsInAnyOrder(list3.toArray()));
//failsCode language: Java (java)

Using Apache Commons

The Apache Commons Collections, an open-source library, provides many useful abstractions to work with Java Collections. We can use the isEqualCollection() method returns true if the two Java Lists are equal in order-agnostic way and cardinality.

List<Integer> list1 = List.of(11, 12, 13, 14, 16);
List<Integer> list2 = List.of(14, 13, 12, 16, 11);

Assert.assertTrue(CollectionUtils
    .isEqualCollection(list1, list2));Code language: Java (java)

As the isEqualCollection() method returns a boolean, we can use it with other Unit Testing Frameworks like TestNG, JUnit, AssertJ, etc.

The method returns false if two Lists have the same elements but different sizes, meaning they have unequal duplicates.

List<Integer> list1 = List.of(11, 12, 13, 14, 16);
List<Integer> list3 = List.of(11, 12, 13, 14, 16, 12);

Assert.assertFalse(CollectionUtils
    .isEqualCollection(list1, list3));Code language: Java (java)

Summary

This practical-oriented tutorial demonstrated ways of Asserting if two Java Lists are equal in an order-agnostic way. We used some of the most popular Unit Testing frameworks like TestNG, JUnit, AssertJ, and Hamcrest to assert if two Java Lists have the same elements and same size, irrespective of the order. We also understood that a utility method from the Apache Commons Collections library could be used to verify that.

Please refer to our GitHub Repository for the complete source code.

Read More: