AssertEquals 2列表忽略顺序

这应该是一个非常简单的问题,我相信。 但不知何故,我无法在Google中find答案。

假设我有2个string列表。 首先包含“stringA”和“stringB” ,第二个包含“stringB”和“stringA” (注意差异顺序)。 我想用JUnit来testing它们是否包含完全相同的string。

是否有任何断言忽略顺序的string的平等检查? 对于给定的例子org.junit.Assert.assertEquals抛出AssertionError

java.lang.AssertionError: expected:<[String A, String B]> but was:<[String B, String A]> 

解决办法是首先对列表进行sorting,然后将它们传递给断言。 但是我希望我的代码尽可能简单和干净。

我使用Hamcrest 1.3JUnit 4.11Mockito 1.9.5

正如你提到你使用Hamcrest,我会select一个集合Matchers

 import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; import static org.junit.Assert.assertThat; public class CompareListTest { @Test public void compareList() { List<String> expected = Arrays.asList("String A", "String B"); List<String> actual = Arrays.asList("String B", "String A"); assertThat("List equality without order", actual, containsInAnyOrder(expected.toArray())); } } 

您可以使用List.containsAll来检查第一个列表包含第二个列表中的每个元素,反之亦然。

 assertTrue(first.size() == second.size() && first.containsAll(second) && second.containsAll(first)); 

这是一个避免二次复杂的解决scheme(多次迭代列表)。 这使用Apache Commons CollectionUtils类创build每个项目的映射到列表中的频率计数本身。 然后它简单地比较两个地图。

 Assert.assertEquals("Verify same metrics series", CollectionUtils.getCardinalityMap(expectedSeriesList), CollectionUtils.getCardinalityMap(actualSeriesList)); 

我也只是发现了CollectionUtils.isEqualCollection,声称做正是在这里被要求…

https://commons.apache.org/proper/commons-collections/apidocs/index.html?org/apache/commons/collections4/CollectionUtils.html

请注意,Roberto Izquierdo的解决scheme通常具有二次复杂性。 HashSets上的解决scheme总是具有线性复杂性:

 assertTrue(first.size() == second.size() && new HashSet(first).equals(new HashSet(second))); 

您可以使用junt-addons jar中的ListAssert 。

 ListAssert.assertEquals(yourList, Arrays.asList(3, 4, 5)); 

为了快速解决,我会检查两种方式:

 assertTrue(first.containsAll(second)); assertTrue(second.containsAll(first)); 

并尝试与相同的元素数量不同的情况下(例如1,1,2和1,2,2),我没有得到误报。