Java AssertEquals 2 列表忽略顺序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22807328/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AssertEquals 2 Lists ignore order
提问by kukis
That should be really simple question I believe. But somehow I can't find answer in Google.
我相信这应该是一个非常简单的问题。但不知何故,我无法在谷歌中找到答案。
Assume that I have 2 Lists of Strings. First contains "String A" and "String B", second one contains "String B" and "String A"(notice difference in order). I want to test them with JUnitto check whether they contains exactly the sameStrings.
假设我有 2 个字符串列表。第一个包含"String A" 和 "String B",第二个包含"String B" 和 "String A"(注意顺序不同)。我想用JUnit测试它们以检查它们是否包含完全相同的字符串。
Is there any assert that checks equality of Strings that ignore order? For given example org.junit.Assert.assertEquals throws AssertionError
是否有任何断言检查忽略顺序的字符串的相等性?对于给定的示例 org.junit.Assert.assertEquals 抛出 AssertionError
java.lang.AssertionError: expected:<[String A, String B]> but was:<[String B, String A]>
Work around is to sort Lists firstly and then pass them to assertion. But I want my code to be as simple and clean as possible.
解决方法是首先对列表进行排序,然后将它们传递给断言。但我希望我的代码尽可能简单和干净。
I use Hamcrest 1.3, JUnit 4.11, Mockito 1.9.5.
我使用Hamcrest 1.3、JUnit 4.11、Mockito 1.9.5。
采纳答案by cheffe
As you mention that you use Hamcrest, I would pick one of the collection Matchers
当您提到您使用 Hamcrest 时,我会选择 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()));
}
}
回答by robertoia
You can use List.containsAllwith JUnit's assertTrue to check that the first list contains every element from the second one, and vice versa.
您可以使用List.containsAll和 JUnit 的assertTrue来检查第一个列表是否包含第二个列表中的每个元素,反之亦然。
assertTrue(first.size() == second.size() &&
first.containsAll(second) && second.containsAll(first));
回答by Kristjan Veskim?e
For a quick fix I would check both ways:
为了快速修复,我会检查两种方式:
assertTrue(first.containsAll(second));
assertTrue(second.containsAll(first));
And trying with a situation where the number of the same elements is different (e.g. 1, 1, 2 and 1, 2, 2) I didn't get false positives.
并尝试在相同元素的数量不同的情况下(例如 1, 1, 2 和 1, 2, 2)我没有得到误报。
回答by leventov
Note that solution by Roberto Izquierdo has quadratic complexity in general. Solution on HashSets always has linear complexity:
请注意,Roberto Izquierdo 的解决方案通常具有二次复杂性。HashSets 上的解决方案总是具有线性复杂度:
assertTrue(first.size() == second.size() &&
new HashSet(first).equals(new HashSet(second)));
回答by akungta
You can use ListAssertthat comes in junit-addons jar.
您可以使用junit-addons jar 中的ListAssert。
ListAssert.assertEquals(yourList, Arrays.asList(3, 4, 5));
回答by Alex Worden
Here's a solution that avoids quadratic complexity (iterating over the lists multiple times). This uses the Apache Commons CollectionUtils class to create a Map of each item to a frequency count itself in the list. It then simply compares the two Maps.
这是一个避免二次复杂度的解决方案(多次迭代列表)。这使用 Apache Commons CollectionUtils 类来创建每个项目到列表中频率计数本身的映射。然后它简单地比较两个地图。
Assert.assertEquals("Verify same metrics series",
CollectionUtils.getCardinalityMap(expectedSeriesList),
CollectionUtils.getCardinalityMap(actualSeriesList));
I also just spotted CollectionUtils.isEqualCollection that claims to do exactly what is being requested here...
我也刚刚发现 CollectionUtils.isEqualCollection 声称完全按照这里的要求执行......
回答by Sujit Joshi
Im late to the party but here's my solution using Junit only. Any thoughts are welcome.
我迟到了,但这是我仅使用 Junit 的解决方案。欢迎任何想法。
List<String> actual = new ArrayList<>();
actual.add("A");
actual.add("A");
actual.add("B");
List<String> expected = new ArrayList<>();
actual.add("A");
actual.add("B");
actual.add("B");
//Step 1: assert for size
assertEquals(actual.size(), expected.size());
//Step 2: Iterate
for(String e: expected){
assertTrue(actual.contains(e));
actual.remove(e);
}
回答by Tinyfool
Collections.sort(excepted);
Collections.sort(actual);
assertEquals(excepted,actual);
回答by davidxxx
With AssertJ, containsExactlyInAnyOrder()
or containsExactlyInAnyOrderElementsOf()
is what you need :
使用 AssertJ,containsExactlyInAnyOrder()
或者containsExactlyInAnyOrderElementsOf()
是您需要的:
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
public class CompareListTest {
@Test
public void compareListWithTwoVariables() {
List<String> expected = Arrays.asList("String A", "String B");
List<String> actual = Arrays.asList("String B", "String A");
Assertions.assertThat(actual)
.containsExactlyInAnyOrderElementsOf(expected);
}
@Test
public void compareListWithInlineExpectedValues() {
List<String> actual = Arrays.asList("String B", "String A");
Assertions.assertThat(actual)
.containsExactlyInAnyOrder("String A", "String B");
}
}
回答by Daniel Avery
Looks like the other answers either reference 3rd party utils, are incorrect, or are inefficient.
看起来其他答案要么参考了 3rd 方实用程序,要么不正确,要么效率低下。
Here's a O(N) vanilla solution in Java 8.
这是 Java 8 中的 O(N) vanilla 解决方案。
public static void assertContainsSame(Collection<?> expected, Collection<?> actual)
{
assert expected.size() == actual.size();
Map<Object, Long> counts = expected.stream()
.collect(Collectors.groupingBy(
item -> item,
Collectors.counting()));
for (Object item : actual)
assert counts.merge(item, -1L, Long::sum) != -1L;
}