简体   繁体   English

Java - 比较两个List的最佳方法 <List<String> &gt;?

[英]Java - best way to compare two List<List<String>>?

What's the best way to compare the String elements of two List<List<String>> ... 比较两个List<List<String>>的String元素的最佳方法是什么...

At the end, I want to know if they contain the same elements (true) or not (false) 最后,我想知道它们是否包含相同的元素(true)或不包含(false)

This two lists I want to compare: 这两个我要比较的列表:

ObservableList<List<String>> fnlData = FXCollections.observableList(new LinkedList<>());;

List<List<String>> fnlDataTMP = new LinkedList<>();

I searched for already answered questions in the forum, but nothing helped me .. 我在论坛中搜索了已经回答的问题,但没有任何帮助我...

Try fnlData.equals(fnlDataTMP) if both list are in order 如果两个列表都是有序的,请尝试fnlData.equals(fnlDataTMP)

or if order does not matter, try creating hash set and then compare using equals 或者如果顺序无关紧要,请尝试创建哈希集,然后使用equals进行比较

new HashSet(fnlData).equals(new HashSet(fnlDataTMP))

looks like you need a double iteration 看起来你需要一个双重迭代

boolean checkEqual(List<List<String>> l1,List<List<String>> l2){
  if(l1.size() != l2.size()){
    return false;
  }
  if(l1.hashCode() != l2.hashCode()){
    return false;
  }
  for(int i=0; i<l1.size(); i++) {
    List<String> curr = l1.get(i);
    List<String> comp = l2.get(i);
    if(curr.size() != comp.size()){
      return false;
    }
    if(curr.hashCode() != comp.hashCode()){
      return false;
    }
    for(int j=0; j<curr.size(); j++) {
      if(!curr.get(j).equals(comp.get(j))){
        return false;
      }
    }
  }
  return true;
}

You can improve the solution checking first difference of hashCode 您可以改进解决方案,检查hashCode的第一个区别

if(l1.hashCode() != l2.hashCode()){
  return false;
}

if hashCode are equal, then check eventually deep difference 如果hashCode相等,那么最终检查深度差异

I don't think there is a way that let's you achieve that out of the box. 我不认为有一种方法可以让你实现开箱即用。

You can do something like the functional java List.join method to quickly generate 2 Lists and compare these: 您可以执行类似函数java List.join方法的操作来快速生成2个列表并进行比较:

List<String> joinedFnlData = jf.data.List.join(fnlData);
List<String> joinedFnlDataTMP = jf.data.List.join(fnlDataTMP);

CollectionUtils.isEqualCollection(joinedFnlData, joinedFnlDataTMP);

Things to note: 注意事项:

  • This is probably not the cheapest operation - so it should not be invoked too often in a time critical scenario (eg UI thread) 这可能不是最便宜的操作 - 因此在时间紧迫的情况下不应该经常调用它(例如UI线程)
  • It does not do a "real" equals - for that you would have to do a nested loop like in the above answer. 它没有“真正的”等于 - 因为你必须像上面的答案那样做一个嵌套循环。 This checks that both joined lists have the same elements with the same cardinality: eg if fnlData has 2 lists with "1" and "2" as the only elements and fnlDataTMP has 1 list with "1", "2" as the elements, this would mark both as equal. 这将检查两个连接列表是否具有相同基数的相同元素:例如,如果fnlData有2个列表,其中“1”和“2”作为唯一元素,fnlDataTMP有1个列表,其中“1”,“2”作为元素,这将标志着两者是平等的。 Depending on your scenario this might be irrelevant - if this is relevant I don't see a way around nested loops. 根据您的情况,这可能是无关紧要的 - 如果这是相关的,我没有看到围绕嵌套循环的方法。

If by same elements you mean that the two lists are exacly the same but in a different order, then i suggest you sort the to lists and then compare them. 如果相同的元素你的意思是两个列表是相同的但是以不同的顺序,那么我建议你对列表进行排序,然后比较它们。

boolean isEqual(List<String> list1, List<String> list2) {
        if (list1.size() != list2.size()) return false;
        Collections.sort(list1);
        Collections.sort(list2);
        int i = 0;
        for (String element : list1) {
            if (!element.equals(list2.get(i))) return false;
            i++;
         }
        return true;
    }

I didn't test it yet! 我还没测试过!

For a Collections (Lists) to be equal, both need to be a proper subset of each other. 为了使集合(列表)相等,两者都需要是彼此的适当子集。 Thus list1.containsAll(list2) and list2.containsAll(list1) . 因此list1.containsAll(list2)list2.containsAll(list1) For a List within a List, you will have to loop, but that's essentially what any built-in library has to do anyway. 对于List中的List,您必须循环,但这实际上是任何内置库必须要做的事情。

I came up with a solution that doesn't need to have two inner loops by using Collections.sort(List list) , which sorts a List in place, and List.containsAll(java.util.Collection) , which compares two Lists for their elements. 我想出了一个解决方案,它不需要有两个内部循环,使用Collections.sort(列表列表) ,它对List进行排序, List.containsAll(java.util.Collection) ,它比较两个列表为他们的元素。

Sample Code: 示例代码:

    //Creating two lists for comparison and their inner lists
    List<List<String>> list1 = new LinkedList<>();
    List<List<String>> list2 = new LinkedList<>();

    LinkedList<String> l11 = new LinkedList<>();
    l11.add("a");
    l11.add("b");
    l11.add("c");

    LinkedList<String> l12 = new LinkedList<>();
    l12.add("d");
    l12.add("e");
    l12.add("f");

    LinkedList<String> l21 = new LinkedList<>();
    l21.add("b");
    l21.add("c");
    l21.add(new String("a"));

    LinkedList<String> l22 = new LinkedList<>();
    l22.add("d");
    l22.add("e");
    l22.add("f");

    list1.add(l11);
    list1.add(l12);
    list2.add(l22);
    list2.add(l21);

    for (List<String> list : list1){
        Collections.sort(list);
    }

    for (List<String> list : list2){
        Collections.sort(list);
    }

    System.out.println(list1.containsAll(list2) && list2.containsAll(list1)); //prints true

If you don't want to change the order of the elements in the inner Lists you can create copies of the outer Lists and perform the operations on them. 如果您不想更改内部列表中元素的顺序,则可以创建外部列表的副本并对其执行操作。

Note: This only works for sortable collections. 注意:这仅适用于可排序的集合。

Store one of the list in a HashMap and then iterate through the other list and check if the Map already contains that KEY. 将其中一个列表存储在HashMap中,然后遍历另一个列表并检查Map是否已包含该KEY。 Ofcourse you have to ensure that KEY types match. 当然,你必须确保KEY类型匹配。

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

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