断言列表<list <string>&gt;包含没有订单的List <string>

时间:2017-06-15 13:06:43

标签: java assert matcher hamcrest

我有List<List<String>>样本数据,如:

("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")

我需要声明,上述样本中存在List<String>,但未考虑订单。

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

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

我知道我可以通过编程方式执行此操作,但是如果有Matcher例如可以提供帮助,则会徘徊。

我已经看到过像:

这样的断言
assertThat(myList, containsInAnyOrder(anotherList.toArray())

但是这只会将一个列表与另一个列表进行比较,而不是列表列表中的列表。

PS:我使用的是Java6,hamcrest-core-1.3,testng-5.14.1

3 个答案:

答案 0 :(得分:3)

我不知道任何匹配器可以做你想做的事情,所以我担心你必须编程。

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

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

boolean result = myList.stream()
    .anyMatch(sublist -> equalsInAnyOrder(sublist, target));

方法equalsInAnyOrder如下:

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

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

    return copy.equals(target);
}

这会对每个子列表进行排序,并将其与目标排序列表进行比较,因此它不是性能方面的,但至少它是简单且简洁的代码。

根据OP的目标编辑Java 6:

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

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

stream() anyMatch已成为while循环:

boolean match = false;
Iterator<List<String>> it = myList.iterator();
while (it.hasNext() && !match) {
    List<String> sublist = it.next();
    match = equalsInAnyOrder(sublist, target);
}

现在方法equalsInAnyOrder看起来像这样:

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

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

    return copy.equals(target);
}

答案 1 :(得分:2)

我没有获得单行解决方案,但我的测试通过了。

我遍历列表列表,将每个列表包装到地图(条目是键,计算值)以及要检查的列表。现在我可以检查是否平等:

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

答案 2 :(得分:0)

我不知道任何Matcher这样做,你是否关心重复? (你的字符串中会有重复的值吗?)

我会那样做:

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

仅当您不关心重复元素并且计数时才会起作用。

("T1#R1", "T1#R1", "T1#R1", "T1#R2")
("T1#R1", "T1#R2", "T1#R2", "T1#R1")
例如,

将返回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;
}

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