Java 断言列表<;列表<;字符串>&燃气轮机;包含列表<;字符串>;毫无秩序

Java 断言列表<;列表<;字符串>&燃气轮机;包含列表<;字符串>;毫无秩序,java,assert,matcher,hamcrest,Java,Assert,Matcher,Hamcrest,我有一个列表,其中包含如下示例数据: ("T1#R1", "T1#R1", "T1#R3", "T1#R4") ("T1#R1", "T1#R1", "T1#R3", "T1#R5") ("T1#R1", "T1#R1", "T1#R6", "T1#R4") ("T1#R1", "T1#R1", "T1#R6", "T1#R5") 我需要声明,上面的示例中存在一个列表,但没有考虑顺序。 例如,以下列表(“T1#R1”、“T1#R1”、“T1#R4”、“T1#R3”)应视为存在于列表中,因为它将

我有一个
列表
,其中包含如下示例数据:

("T1#R1", "T1#R1", "T1#R3", "T1#R4")
("T1#R1", "T1#R1", "T1#R3", "T1#R5")
("T1#R1", "T1#R1", "T1#R6", "T1#R4")
("T1#R1", "T1#R1", "T1#R6", "T1#R5")
我需要声明,上面的示例中存在一个
列表,但没有考虑顺序。

例如,以下列表
(“T1#R1”、“T1#R1”、“T1#R4”、“T1#R3”)
应视为存在于
列表中,因为它将包含与第一个列表相同的项目,但顺序不同。

另一方面,
(“T1#R1”、“T1#R3”、“T1#R4”、“T1#R3”)
不应被视为存在于列表中,因为它具有相同的项,但具有不同的计数。

我知道我可以通过编程实现这一点,但我想知道是否有一个
Matcher
可以提供帮助。

我见过这样的断言:

assertThat(myList, containsInAnyOrder(anotherList.toArray())
但这只是比较一个列表和另一个列表,而不是列表列表中的列表。


PS:我使用的是Java6、hamcrest-core-1.3、testng-5.14.1,我不知道有哪一个匹配器能做到这一点,你是否关心重复?(字符串中是否有重复的值?)

我会做这样的事:

private boolean containsInAnyOrder(List<List<String>> container, List<String> list)
{
  for (List<String> list1 : container)
  {
     if(list.size()==list1.size())
     {
        if(list1.containsAll(list))
        {
           return true;
        }
     }
  }
  return false;
}
例如,将返回true。你有复本吗?(与Set解决方案相同,由于相同的原因,它将不起作用)

如果是重复的,您需要计算每个项目:

private boolean containsInAnyOrder(List<List<String>> container, List<String> list)
{
  for (List<String> list1 : container)
  {
     if(list.size()==list1.size())
     {
        boolean found = true;
        for(String string : list)
        {
           if (list.stream().filter(pS -> pS.equals(string)).count() != list1.stream().filter(pS -> pS.equals(string)).count())
           {
              found = false;
           }
        }
        if(found)
        {
           return true;
        }
     }
  }
  return false;
}
private boolean containsInAnyOrder(列表容器,列表列表)
{
对于(列表1:容器)
{
if(list.size()==list1.size())
{
布尔值=真;
用于(字符串:列表)
{
if(list.stream().filter(pS->pS.equals(string)).count()!=list1.stream().filter(pS->pS.equals(string)).count())
{
发现=错误;
}
}
如果(找到)
{
返回true;
}
}
}
返回false;
}

请注意,它没有经过优化,内部for循环可能会在不匹配的情况下停止。

我不知道有任何匹配器可以满足您的要求,因此我担心您必须对其进行编程

我只需对目标列表进行排序,然后迭代子列表,直到找到匹配项:

List<String> target = new ArrayList<>(anotherList);
target.sort();

boolean result = myList.stream()
    .anyMatch(sublist -> equalsInAnyOrder(sublist, target));
List<String> target = new ArrayList<>(anotherList);
Collections.sort(target);
这将对每个子列表进行排序,并将其与目标排序列表进行比较,因此它不符合性能要求,但至少是简单简洁的代码


根据OP针对Java 6的需要进行编辑:

该逻辑与Java8版本中的逻辑完全相同。首先对目标列表进行排序,然后比较每个子列表,直到找到匹配项:

List<String> target = new ArrayList<>(anotherList);
target.sort();

boolean result = myList.stream()
    .anyMatch(sublist -> equalsInAnyOrder(sublist, target));
List<String> target = new ArrayList<>(anotherList);
Collections.sort(target);
现在方法
equalsinorder
如下所示:

public <T> boolean equalsInAnyOrder(List<T> sublist, List<T> target) {

    List<String> copy = new ArrayList<>(sublist);
    Collections.sort(copy);

    return copy.equals(target);
}
public boolean equalsinorder(列表子列表,列表目标){
列表副本=新的ArrayList(子列表);
收藏。分类(复印);
返回副本.equals(目标);
}

我没有一行解决方案,但我的测试通过了

我遍历列表列表,将每个列表包装成一个映射(条目是键,计算值)并检查列表。现在我可以检查是否相等:

public void listOfLists() throws Exception {
    List<List<String>> myList = Arrays.asList(
        Arrays.asList("T1#R1", "T1#R1", "T1#R3", "T1#R4"),
        Arrays.asList("T1#R1", "T1#R1", "T1#R3", "T1#R5"),
        Arrays.asList("T1#R1", "T1#R1", "T1#R6", "T1#R4"),
        Arrays.asList("T1#R1", "T1#R1", "T1#R6", "T1#R5"));
    List<String> easy = Arrays.asList("T1#R1", "T1#R1", "T1#R4", "T1#R3");
    List<String> duplicate = Arrays.asList("T1#R1", "T1#R5", "T1#R1", "T1#R6");
    List<String> noMatch = Arrays.asList("T1#R1", "T1#R5", "T1#R6");

    Map<String, Integer> easyCount = countEntries(easy);
    Map<String, Integer> duplicateCount = countEntries(duplicate);
    Map<String, Integer> noCount = countEntries(noMatch);

    for (List<String> l : myList) {
        Map<String, Integer> countedEntries = countEntries(l);
        if (countedEntries.equals(easyCount)) {
            System.out.println("easy matches");
        }
        if (countedEntries.equals(duplicateCount)) {
            System.out.println("duplicate matches");
        }
        if (countedEntries.equals(noCount)) {
            System.out.println("Damn!");
        }
    }
}

private Map<String, Integer> countEntries(List<String> original) {
    return original.stream()
        .collect(Collectors.toMap(Function.identity(), s -> 1, Integer::sum));
}

我会反复浏览您的列表,将每个列表包装成一个
集合
,以及检查和比较集合的列表,因为没有订单规范。我可能需要更改我的示例,因为列表可能有重复的元素,所以一个集合不必计算列表中某个元素的重复次数。我可以有重复项,并且出现的次数应该匹配。我将更新我的问题。在这种情况下,您将需要计数和比较计数。我认为hasItems不起作用。如果@Jorn Vernee谈论的是hamcrest matcher,它将在第一次匹配后停止。我将尝试一下,并进行必要的更改以使其适应Java6,因为这是我正在使用的版本。哦,天哪。。。现在您已将帖子更新到java 6。。。我不会删除答案,如果它可以帮助你作为一个理想的想法,比我的解决方案,我的开销少think@StefanWarminski您的解决方案可能会有更多的开销,因为您正在流式处理每个子列表,但它是
O(nx m)
,而我的是
O(nx m log m)
,因此您的解决方案更适合于较大的列表。此解决方案看起来更对我来说是“可读的”,并且也适用于Java6,这就是为什么我将它标记为正确的。
public void listOfLists() throws Exception {
    List<List<String>> myList = Arrays.asList(
        Arrays.asList("T1#R1", "T1#R1", "T1#R3", "T1#R4"),
        Arrays.asList("T1#R1", "T1#R1", "T1#R3", "T1#R5"),
        Arrays.asList("T1#R1", "T1#R1", "T1#R6", "T1#R4"),
        Arrays.asList("T1#R1", "T1#R1", "T1#R6", "T1#R5"));
    List<String> easy = Arrays.asList("T1#R1", "T1#R1", "T1#R4", "T1#R3");
    List<String> duplicate = Arrays.asList("T1#R1", "T1#R5", "T1#R1", "T1#R6");
    List<String> noMatch = Arrays.asList("T1#R1", "T1#R5", "T1#R6");

    Map<String, Integer> easyCount = countEntries(easy);
    Map<String, Integer> duplicateCount = countEntries(duplicate);
    Map<String, Integer> noCount = countEntries(noMatch);

    for (List<String> l : myList) {
        Map<String, Integer> countedEntries = countEntries(l);
        if (countedEntries.equals(easyCount)) {
            System.out.println("easy matches");
        }
        if (countedEntries.equals(duplicateCount)) {
            System.out.println("duplicate matches");
        }
        if (countedEntries.equals(noCount)) {
            System.out.println("Damn!");
        }
    }
}

private Map<String, Integer> countEntries(List<String> original) {
    return original.stream()
        .collect(Collectors.toMap(Function.identity(), s -> 1, Integer::sum));
}
easy matches
duplicate matches