【问题标题】:Java - best way to compare two List<List<String>>?Java - 比较两个 List<List<String>> 的最佳方法?
【发布时间】:2015-07-29 10:52:48
【问题描述】:

比较两个List&lt;List&lt;String&gt;&gt;的String元素的最佳方法是什么...

最后,我想知道它们是否包含相同的元素(真)或不(假)

我想比较这两个列表:

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

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

我在论坛中搜索了已经回答的问题,但没有任何帮助..

【问题讨论】:

  • 你检查过这个吗? [链接][1][1]:stackoverflow.com/questions/14545303/…看看吧。
  • 你试过fnlData.equals(fnlDataTMP)吗?
  • @Lathy 我不能使用 CollectionUtils ...
  • @Tom 是的,它没有用
  • List&lt;List&lt;String&gt;&gt;合并为一个List,进行普通的列表比较。

标签: java list compare


【解决方案1】:

如果两个列表都按顺序排列,请尝试fnlData.equals(fnlDataTMP)

或者如果顺序无关紧要,请尝试创建哈希集,然后使用 equals 进行比较

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

【讨论】:

  • @tobias_k 不同的List 类型,如果它们不覆盖equals,那么就没有问题。
  • @Tom 我以为他们也会检查班级是否相等,但显然他们没有。刚刚检查了ArrayListLinkedList,它们比较相等(内容相等)。感谢您的指点。不过,似乎 OP 已经尝试过了,但没有奏效......
  • @tobias_k ArrayListLinkedList 不覆盖 equals 方法,所以使用 AbstractList 的版本,它只检查两者是否都是 List 类型。
【解决方案2】:

我认为没有办法让您开箱即用地实现这一目标。

您可以执行类似functional java List.join 方法的操作来快速生成 2 个列表并进行比较:

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

CollectionUtils.isEqualCollection(joinedFnlData, joinedFnlDataTMP);

注意事项:

  • 这可能不是最便宜的操作 - 因此在时间紧迫的场景(例如 UI 线程)中不应过于频繁地调用它
  • 它不会执行“真正的”等于 - 因为您必须像上面的答案那样执行嵌套循环。这将检查两个连接列表是否具有具有相同基数的相同元素:例如如果 fnlData 有 2 个列表,其中只有“1”和“2”作为唯一元素,并且 fnlDataTMP 有 1 个列表,其中“1”、“2”作为元素,这会将两者标记为相等。根据您的情况,这可能无关紧要 - 如果这是相关的,我看不到嵌套循环的方法。

【讨论】:

  • 不知何故我无法使用/导入 jf 和 CollectionUtils
  • CollectionUtils 来自 apache-commons-collections 库。功能java jar文件可以在这里下载:code.google.com/p/functionaljava
【解决方案3】:

如果使用相同的元素,您的意思是两个列表完全相同但顺序不同,那么我建议您对列表进行排序,然后进行比较。

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

我还没测试呢!

【讨论】:

  • 它们并不完全相同,可能是一个列表只有一个不同的字符串
  • @InfernoVol 你说,你想知道两者是否包含相同的元素..如果已经知道,他们不知道,那你为什么要检查呢?
【解决方案4】:

要使集合(列表)相等,两者必须是彼此的真子集。因此list1.containsAll(list2)list2.containsAll(list1)。 对于列表中的列表,您将不得不循环,但这基本上是任何内置库都必须做的事情。

【讨论】:

    【解决方案5】:

    看起来你需要两次迭代

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

    您可以改进检查 hashCode 的一阶差分的解决方案

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

    如果 hashCode 相等,则检查最终深度差异

    【讨论】:

    • 外部列表的大小可能超过 100k,因此需要花费大量时间
    • @InfernoVol 如果您对列表一无所知,那么您必须遍历它们。也许你的情况有些特别。为了提供更快的搜索,我们需要查看您的场景。
    • 列表可能包含如下内容:i.imgur.com/jfgcixg.png 行是外列表,列是内列表。例如,此文件有 ~90 000 行。我可能是,在 tempList 中只有一个 String 不同....
    • 一种更快捷的方法是在使用迭代之前检查 hashCode。如果 hashCode 不相等,那么您可以确保您的列表不同
    【解决方案6】:

    我想出了一个不需要有两个内部循环的解决方案,它使用 Collections.sort(List list) 对 List 进行就地排序,List.containsAll(java.util.Collection) 比较两个 List 的元素。

    示例代码:

        //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
    

    如果您不想更改内部列表中元素的顺序,您可以创建外部列表的副本并对其执行操作。

    注意:这仅适用于可排序的集合。

    【讨论】:

      【解决方案7】:

      将其中一个列表存储在 HashMap 中,然后遍历另一个列表并检查 Map 是否已包含该 KEY。当然,您必须确保 KEY 类型匹配。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-12-11
        • 2020-01-26
        • 1970-01-01
        • 2014-12-03
        • 1970-01-01
        • 1970-01-01
        • 2013-06-08
        相关资源
        最近更新 更多