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.