我有两个非常大的名单。让我们说几百万元素。两个列表已经以相同的方式排序。现在我需要检查两个列表是否相等。 做这个的最好方式是什么? 现在我的想法是使用Assert.assertEquals比较行到行。
for(int i=0;i<Math.max(list1.size(),list2.size()),i++){
Assert.assertEquals(list1.get(i),list2.get(i));
}
不幸的是,如果列表中有数百万个对象,我会担心此解决方案的性能。此外,如果列表不相等,那么我需要知道差异在哪里。
有没有更好,更快,更自信的解决方案呢?
答案 0 :(得分:3)
如果列表相同,最后它会进行O(n)操作。所以我会简单地使用:
Assert.assertEquals(list1, list2);
将依赖List::equals
来比较列表 - 我怀疑你可以比这更有效率,除非你有关于列表内容的具体信息。
如果列表不相等,您应该得到一个显示差异的异常。
答案 1 :(得分:1)
更简单的方法是使用您无论如何使用的列表大小:
if(list1.size() > list2.size()) {
list1.removeAll(list2);
// print the list1 (discrepancies)
Assert.fail("Lists are not equal");
} else if
...// same for list2.size() > list1.size()
} else {
list1.removeAll(list2);
if(!list1.isEmpty()) {
// print the discrepancies
Assert.fail("Lists are not equal");
}
}
答案 2 :(得分:1)
性能主要取决于您将用于执行它的Collection 类和方法。
正如您提到的代码,它是使用 get 列表方法进行迭代和比较,我们需要知道实现列表的哪个集合类具有更好的 get 性能方法..
for(int i=0;i<Math.max(list1.size(),list2.size()),i++){
Assert.assertEquals(list1.get(i),list2.get(i));
}
如果您使用列表实施的 LinkedList 获取方法,那么获取单个对象的效果顺序将 O(n / 4)平均值
如果您使用列表实施 ArrayList get方法,则获取单个对象的效果顺序将为 O(1)。
因此,我们可以说基于您的代码的比较对于 ArrayList 会更快。
答案 3 :(得分:1)
这很简单:当你想确定两个列表相等时 - 你必须按元素进行比较。当然,只有当两个列表具有相同的大小时才会这样做。
因此你总是处理O(n)。
Java ArrayLists已经是数据结构的不错选择。
唯一潜在的优化:通过使用多个线程比较子列表可以更快地解决此问题。所以parallelStream()可能是你的朋友。
或者 - 当列表包含int,double ...原始值时 - 那么您可以考虑使用普通旧数组而不是基于集合的列表。
答案 4 :(得分:0)
您应该将它们存储在二叉树中。与列表相比,搜索速度非常快。