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