【问题标题】:Compare two Linked Lists比较两个链表
【发布时间】:2015-06-14 08:42:10
【问题描述】:

在 Java 中比较两个链接列表的最佳方法是什么,我有两个列表,并希望确保一个列表中的所有元素都不在另一个列表中。像这样的工作两个列表都是 LocalDates 列表。

boolean doesNotContain (LinkedList L1, LinkedList L2) { 
        for(LocalDate d:L1) { 
            if(l2.contains(d){
                return false; 

            } 
        }
       return true;    
}    

【问题讨论】:

标签: java linked-list


【解决方案1】:

您的解决方案适用于 N^2 复杂度。如果您对两个列表进行排序并在一个循环中对其进行迭代,则可以在 N log N 中执行 int(即排序复杂度)。

您还可以创建两个新的Sets 包含两个列表中的元素,然后使用containsAll() 方法 - 它会完成所有工作。这是一个干净且易于理解的解决方案。不过可能会消耗内存。

比较方法取决于方法 equals()hashCode() - 如果您没有在 LocalDate 类中正确覆盖它们,您将不会得到好的结果。

BTW1: return after break 是死码

BTW2:用“not”命名方法似乎是个坏主意。您很快就会发现自己在使用!notFulfills( !notContains(sdflasdf))。祝你好运,试图弄清楚这是做什么的。

【讨论】:

    【解决方案2】:

    由于您的doesNotContain(..) 实现接近于containsAll(..) 实现,我建议使用那个。如果您执行list1.containsAll(list2),实现将遍历list2 的所有元素以检查list1 中是否存在相等的对象。这就是您需要在 LocalDate 中覆盖 public boolean equals(Object obj) 的原因。

    在下面找到一个小例子来展示 containsAll(..) 所做的事情

    运行检查的主要过程

    public static void main(String[] args) throws Exception {
        List<LocalDate> list1 = new LinkedList<>();
        list1.add(new LocalDate("112233"));
        list1.add(new LocalDate("223344"));
    
        List<LocalDate> list2 = new LinkedList<>();
        list2.add(new LocalDate("112233"));
        list2.add(new LocalDate("112233"));
    
        System.out.println("list1 = " + list1);
        System.out.println("list2 = " + list2);
    
        System.out.println("list1.containsAll(list2) = " + list1.containsAll(list2));
        System.out.println("list2.containsAll(list1) = " + list2.containsAll(list1));
    }
    

    如果您在不覆盖 equals 方法的情况下实现 LocalDate,则只有在比较 same 对象的引用时,equals 才会为真。

    // a naive implementation for demonstration purpose
    class LocalDate {
    
        String hour;
        String minute;
        String second;
    
        LocalDate(String string) {
            hour = string.substring(0, 2);
            minute = string.substring(2, 4);
            second = string.substring(4, 6);
        }
    
        @Override
        public String toString() {
            return String.format("LocalDate{%s%s%s} - hashcode: %d", hour, minute, second, this.hashCode());
        }
    }
    

    结果是

    list1 = [LocalDate{112233} - hashcode: 33039820, LocalDate{223344} - hashcode: 31311199]
    list2 = [LocalDate{112233} - hashcode: 13177912, LocalDate{112233} - hashcode: 21924553]
    list1.containsAll(list2) = false
    list2.containsAll(list1) = false
    

    如果你重写了 equals 方法(为了演示目的,已经省略了哈希码)

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final LocalDate other = (LocalDate) obj;
        System.out.println(toString() + ".equals(" + obj.toString() + ')');
        if (!Objects.equals(this.hour, other.hour)) {
            return false;
        }
        if (!Objects.equals(this.minute, other.minute)) {
            return false;
        }
        if (!Objects.equals(this.second, other.second)) {
            return false;
        }
        return true;
    }
    

    输出将是

    list1 = [LocalDate{112233} - hashcode: 33336787, LocalDate{223344} - hashcode: 12767201]
    list2 = [LocalDate{112233} - hashcode: 31311199, LocalDate{112233} - hashcode: 13177912]
    // generated output by the method containsAll(..)
    LocalDate{112233} - hashcode: 31311199.equals(LocalDate{112233} - hashcode: 33336787)
    LocalDate{112233} - hashcode: 13177912.equals(LocalDate{112233} - hashcode: 33336787)
    list1.containsAll(list2) = true
    // generated output by the method containsAll(..)
    LocalDate{112233} - hashcode: 33336787.equals(LocalDate{112233} - hashcode: 31311199)
    LocalDate{223344} - hashcode: 12767201.equals(LocalDate{112233} - hashcode: 31311199)
    LocalDate{223344} - hashcode: 12767201.equals(LocalDate{112233} - hashcode: 13177912)
    list2.containsAll(list1) = false
    

    根据打印出来的Object.hashcode(),您可以很容易地看到 containsAll() 方法遍历了您调用该方法的列表中的所有元素。

    如果您想改进检查,您需要先明确以下几点 - 列表中的元素是否唯一 -> 然后最好使用 Set - 列表必须具有相同数量的元素 -> 如果是,您可以在第一步比较它们的大小 - 如果您只需要检查 list2 是否只有 list1 中的元素(意味着列表包含唯一值)-> 调用 list2 上的 containsAll 方法 - 之前对列表进行排序也可能是值得的(取决于包含的数据)

    如果没有这些信息,就不可能在所有情况下给出the best 的建议。

    【讨论】:

      猜你喜欢
      • 2020-01-25
      • 1970-01-01
      • 2021-04-24
      • 1970-01-01
      • 2014-12-05
      • 1970-01-01
      • 2018-02-25
      • 2012-03-01
      • 2013-03-27
      相关资源
      最近更新 更多