如何检查一个数组是否是二维数组中的元素之一
How to check if an array is one of the elements in a two-dimensional array
我试图使用 Hamcrest 库提供的标准 Collection.isIn 匹配器断言字符串元素数组是二维数组的元素之一.不幸的是收到以下断言异常:
java.lang.AssertionError:
Expected: one of {["A", "B", "C"], ["A", "B", "C"]}
but: was ["A", "B", "C"]
代码:
String[][] expected = new String[][] { { "A", "B", "C" }, { "A", "B", "C" } };
String[] actual = new String[] { "A", "B", "C" };
assertThat(actual, isIn(expected));
我可以以这种方式验证使用 hamcrest 吗?还是我需要为给定场景创建自己的匹配器?
您的数组可能包含与 expected
中的数组相同的内容,但它不是同一个对象。
我猜这个问题是因为该方法比较的是对象,而不是内容。基本上,即使两者具有相同的内容,它们也不是同一个对象。 See here in the docs
改为这样做:
String[] actual = new String[]{"A1 C1 E1 F1 J1", "A1 C1 E1 F1 K1", "A1 B1 G1 H1"};
String[][] expected = new String[][]{actual, {"A1 C1 E1 F1 J1", "A1 C1 E1 F1 K1", "A1 B1 G1 H1"}};
首先,你最好使用 List<>
而不是数组。
其次,是的,如果你坚持使用数组,你将需要自己编写'array-contains-element'函数。您可以在数组的主要维度上使用循环来实现此功能,调用 Arrays.equals()
方法来比较两个一维数组的内容。
在您的上下文中 collection.IsIn 的问题是您的列表元素是一个数组,它将使用 Array#equals 来比较每个元素。
更具体地说
// It will print false, because Array.equals check the reference
// of objects, not the content
System.out.println(actual.equals(new String[]{"A1 C1 E1 F1 J1", "A1 C1 E1 F1 K1", "A1 B1 G1 H1"}));
所以我建议创建一个使用 java 中的 Arrays.equals 的自定义匹配器。它将为您比较数组的内容。类似下面的代码:
public boolean matches(Object item) {
final String[] actualStringArray = (String [])item;
List<String[]> listOfStringArrays = Arrays.asList(expectedStringMatrix);
for (String[] stringArray : listOfStringArrays) {
// Arrays.equals to compare the contents of two array!
if (Arrays.equals(stringArray, actualStringArray)) {
return true;
}
}
return false;
}
问题是,当对象是数组时,Object.equals()
不会执行您可能期望的操作。您可能已经知道,您必须使用 Arrays.equals()
——但 Hamcrest isIn()
不允许这样做。
可能最简单的解决方案是转换为 List
,即使只是为了测试——因为 List.equals()
像 Hamcrest 期望的那样工作:
...
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.collection.IsIn.in;
...
String[][] expected = new String[][] { { "A", "B", "C" }, { "A", "B", "C" } };
Object[] expectedLists = Arrays.stream(expected).map(Arrays::asList).toArray();
String[] actual = new String[] { "A", "B", "C" };
assertThat(Arrays.asList(actual), is(in(expectedLists)));
我试图使用 Hamcrest 库提供的标准 Collection.isIn 匹配器断言字符串元素数组是二维数组的元素之一.不幸的是收到以下断言异常:
java.lang.AssertionError:
Expected: one of {["A", "B", "C"], ["A", "B", "C"]}
but: was ["A", "B", "C"]
代码:
String[][] expected = new String[][] { { "A", "B", "C" }, { "A", "B", "C" } };
String[] actual = new String[] { "A", "B", "C" };
assertThat(actual, isIn(expected));
我可以以这种方式验证使用 hamcrest 吗?还是我需要为给定场景创建自己的匹配器?
您的数组可能包含与 expected
中的数组相同的内容,但它不是同一个对象。
我猜这个问题是因为该方法比较的是对象,而不是内容。基本上,即使两者具有相同的内容,它们也不是同一个对象。 See here in the docs
改为这样做:
String[] actual = new String[]{"A1 C1 E1 F1 J1", "A1 C1 E1 F1 K1", "A1 B1 G1 H1"};
String[][] expected = new String[][]{actual, {"A1 C1 E1 F1 J1", "A1 C1 E1 F1 K1", "A1 B1 G1 H1"}};
首先,你最好使用 List<>
而不是数组。
其次,是的,如果你坚持使用数组,你将需要自己编写'array-contains-element'函数。您可以在数组的主要维度上使用循环来实现此功能,调用 Arrays.equals()
方法来比较两个一维数组的内容。
在您的上下文中 collection.IsIn 的问题是您的列表元素是一个数组,它将使用 Array#equals 来比较每个元素。
更具体地说
// It will print false, because Array.equals check the reference
// of objects, not the content
System.out.println(actual.equals(new String[]{"A1 C1 E1 F1 J1", "A1 C1 E1 F1 K1", "A1 B1 G1 H1"}));
所以我建议创建一个使用 java 中的 Arrays.equals 的自定义匹配器。它将为您比较数组的内容。类似下面的代码:
public boolean matches(Object item) {
final String[] actualStringArray = (String [])item;
List<String[]> listOfStringArrays = Arrays.asList(expectedStringMatrix);
for (String[] stringArray : listOfStringArrays) {
// Arrays.equals to compare the contents of two array!
if (Arrays.equals(stringArray, actualStringArray)) {
return true;
}
}
return false;
}
问题是,当对象是数组时,Object.equals()
不会执行您可能期望的操作。您可能已经知道,您必须使用 Arrays.equals()
——但 Hamcrest isIn()
不允许这样做。
可能最简单的解决方案是转换为 List
,即使只是为了测试——因为 List.equals()
像 Hamcrest 期望的那样工作:
...
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.collection.IsIn.in;
...
String[][] expected = new String[][] { { "A", "B", "C" }, { "A", "B", "C" } };
Object[] expectedLists = Arrays.stream(expected).map(Arrays::asList).toArray();
String[] actual = new String[] { "A", "B", "C" };
assertThat(Arrays.asList(actual), is(in(expectedLists)));