3

I want to compare if a list is a sublist of another list

Assume I have the following lists

List<String> checkList = Arrays.asList("a", "d");

List<String> actualList = Arrays.asList("a", "b", "c", "d");

I want to check if actualList contains checkList . I can iterate each value and compare. But is there any hamcrest matcher that will do the job

For ex.

a,d should pass

a,b,c should pass

But a,e should fail

the hasItems supports the strings to be passed individually, and contains is checking for all the values, in supports an item to be present in a list. But I wanted

assertThat(actualList,containsList(checkList))

Is there any inbuilt matcher available or do I need to write custom matcher?

Madhan
  • 5,750
  • 4
  • 28
  • 61
  • Have a look at [`IsIterableContainingInOrder`](http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/collection/IsIterableContainingInOrder.html), maybe that's what you need. [This question](https://stackoverflow.com/questions/15609132/how-to-check-if-collection-contains-items-in-given-order-using-hamcrest) is relevant, too. – deHaar Oct 28 '19 at 13:52
  • @deHaar that will evaluate only one item. not list – Madhan Oct 28 '19 at 13:55
  • OK, maybe you have to write your own `Matcher`, see [this question](https://stackoverflow.com/questions/34589894/hamcrest-matcher-for-a-sublist-partial-match). – deHaar Oct 28 '19 at 13:59
  • 1
    `hasItems` should work. Just convert your list to an array. `checkList.toArray(new String[0])` – Sotirios Delimanolis Oct 28 '19 at 14:01

1 Answers1

5

hasItems accepts a varargs parameter, so you can just convert your list to an array and pass it (alternatively, just declare it as an array to begin with):

final List<String> checkList = Arrays.asList("a", "d");
// final String[] checkListAsArray = new String[] { "a", "d" };
final String[] checkListAsArray = checkList.toArray(new String[checkList.size()]);
final List<String> actualList = Arrays.asList("a", "b", "c", "d");
assertThat(actualList, Matchers.hasItems(checkListAsArray));

The order of the checkList is not important.

If you swap the roles of checkList and actualList, you could also write:

assertThat(checkList, everyItem(isIn(actualList)));

This is probably more readable than:

assertTrue(actualList.stream().allMatch(checkList::contains));
sfiss
  • 2,119
  • 13
  • 19
  • 1
    +1 for `assertThat(checkList, everyItem(isIn(actualList)))`. In particular, the output of this on failure is much more readable than just asserting equality of two lists, or the `assertTrue` option. And it's a lot fewer lines than converting to an array :) – Rik Apr 28 '21 at 17:47
  • `isIn` is deprecated in the newer versions, but `is(in(...))` can be used instead or simply `in(...)` – TomasZ. Sep 10 '21 at 11:21