简体   繁体   English

如何检查数组是否是二维数组中的元素之一

[英]How to check if an array is one of the elements in a two-dimensional array

I am trying to assert that an array of string elements is one of the elements of a 2-dimensional array using the standard Collection.isIn matcher provided with Hamcrest library.我试图使用 Hamcrest 库提供的标准Collection.isIn匹配器来断言字符串元素数组是二维数组的元素之一。 Unfortunately receiving the following assertion exception:不幸的是收到以下断言异常:

java.lang.AssertionError: 
Expected: one of {["A", "B", "C"], ["A", "B", "C"]}
   but: was ["A", "B", "C"]

Code:代码:

String[][] expected = new String[][] { { "A", "B", "C" }, { "A", "B", "C" } };
String[] actual = new String[] { "A", "B", "C" };

assertThat(actual, isIn(expected));

Can I validate using hamcrest in such a manner?我可以以这种方式使用 hamcrest 进行验证吗? Or do I need to create my own matcher for the given scenario?或者我是否需要为给定的场景创建我自己的匹配器?

The issue is that Object.equals() doesn't do what you might expect when the objects are arrays.问题是Object.equals()在对象是数组时不会执行您可能期望的操作。 As you probably already know, you have to use Arrays.equals() -- but Hamcrest isIn() does not allow for this.您可能已经知道,您必须使用Arrays.equals() -- 但 Hamcrest isIn()不允许这样做。

Probably the simplest solution is to convert to List even if only for the test -- because List.equals() works as Hamcrest expects:可能最简单的解决方案是转换为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)));

您的数组可能包含与expected的数组相同的内容,但它不是同一个对象。

First of all, you would be better off using List<> instead of arrays.首先,最好使用List<>而不是数组。

Secondly, yes, if you insist on using arrays, you will need to write your own 'array-contains-element' function.其次,是的,如果您坚持使用数组,则需要编写自己的“数组包含元素”函数。 You can implement this function using a loop over the major dimension of the array, invoking the Arrays.equals() method to compare the contents of two one-dimensional arrays.您可以在数组的主要维度上使用循环来实现此函数,调用Arrays.equals()方法来比较两个一维数组的内容。

I'm guessing the issue is because the method compares objects, and not contents.我猜这个问题是因为该方法比较的是对象,而不是内容。 Basically, even though both have the same content, they are not the same object.基本上,即使两者具有相同的内容,它们也不是同一个对象。 See here in the docs 在文档中看到这里

Do this instead:改为这样做:

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"}};

The problem with collection.IsIn in your context, is that your elements of your list is an array and it will use the Array#equals to compare each element. collection.IsIn 在您的上下文中的问题在于,您的列表元素是一个数组,它将使用 Array#equals 来比较每个元素。

More specifically更具体地说

// 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"}));

So I suggest creating a custom matcher that uses Arrays.equals from java.所以我建议创建一个使用 java 中的 Arrays.equals 的自定义匹配器。 It will compare the content of arrays for you.它将为您比较数组的内容。 Something like code below:类似于下面的代码:

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM