Explain Codes LogoExplain Codes Logo

Hamcrest compare collections

java
assertions
collections
testing
Nikita BarsukovbyNikita Barsukov·Feb 9, 2025
TLDR

To assert collections have the same elements but don't care about their order, use Hamcrest's containsInAnyOrder:

import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; // A fruit basket comparison, order doesn't matter, everyone loves fruit! assertThat(Arrays.asList("apple", "banana"), containsInAnyOrder("banana", "apple"));

For the times when you do care about order, switch to contains:

import static org.hamcrest.Matchers.contains; // Apple before banana, always! It's the alphabetically correct way. assertThat(Arrays.asList("apple", "banana"), contains("apple", "banana"));

Both examples show how to use Hamcrest matchers for comparing collections.

Comparing list equality

If you need to check if two lists are identical, here is how you do it:

import static org.junit.Assert.assertEquals; // Asserts that apple always comes before banana, just like nature intended assertEquals(Arrays.asList("apple", "banana"), Arrays.asList("apple", "banana"));

Type check: the silent hero of code

Make sure your list's type is the one that the matcher expects:

List<Agent> agentList = Arrays.asList(new Agent("007"), new Agent("006")); Matcher<Iterable<? extends Agent>> matcher = containsInAnyOrder(new Agent("006"), new Agent("007")); assertThat(agentList, matcher); // Silently checking behind the scene, like a true agent.

Picking out items in a haystack

Looking for the proverbial one

Using hasItem, you can check for a single item:

import static org.hamcrest.Matchers.hasItem; assertThat(Arrays.asList("apple", "banana"), hasItem("apple")); // finding that forbidden fruit

All for one, or just more than one

To check for multiple items, use hasItems:

import static org.hamcrest.Matchers.hasItems; assertThat(Arrays.asList("apple", "banana", "cherry"), hasItems("cherry", "banana")); // more fruits, yay!

The super-matchmaker

Combine multiple matchers by using allOf:

import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.everyItem; import static org.hamcrest.Matchers.greaterThan; // Is 2 in the list and is every item is positive because we only want positive vibes assertThat(Arrays.asList(1, 2, 3), allOf(hasItem(2), everyItem(greaterThan(0))));

Property matchers, the unsung heroes

hasProperty can be employed for comparing object attributes within collections:

import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasProperty; List<Person> persons = Arrays.asList(new Person("John", 30), new Person("Jane", 25)); assertThat(persons, hasItem(hasProperty("name", is("Jane")))); // Where's Jane? Oh, here she is.

Remember to import org.hamcrest.Matchers.is.

Pay attention to details

Converting lists to arrays for fun and profit

When it's easier to compare by converting a list to an array:

String[] expectedArray = {"apple", "banana"}; List<String> actualList = Arrays.asList("banana", "apple"); assertThat(actualList, containsInAnyOrder(expectedArray)); // back to fruit, arrays style!

Avoiding the common "whoops"!

When using matchers, watch out for type safety and correct usage to avoid funny but hard-to-find bugs.

Readable assertions: we got you covered.

To make your assertions more readable, import containsInAnyOrder statically.