我将两个arraylist<String>
与列表一的平均大小50K
和列表二200K
进行比较。
int size = MsSQLList.size();
for (int index = 0; index < size; index++) {
if (!oracleSQLList.contains(MsSQLList.get(index))) {
logger.debug(" *[POSSIBLE MISS]* Oracle missing record id: "
+ (MsSQLList.get(index)));
}
}
列表中的数据字符串为16个字符,即A89EERDD12312445等...我在进入上述循环之前在两者上运行Collection.sort(list)
。
平均比较时间接近160秒。这是最好的方法还是我们可以做得更好?
问题2: 您猜到的结果是从DB获取的,持续5天。
如果我选择30天作为我的间隔,理想情况下我可以获得110万条记录。由于此负载,旧数组列表实现抛出OutofMemory。
因此,快速跟进问题我现在可以将负载推回到110万,间隔30天吗?
答案 0 :(得分:2)
如果值是唯一的,请将它们放在Set
s而不是数组列表中。
假设你有
Set<String> oracleSet = new HashSet<>();
Set<String> msSet = new HashSet<>();
然后在填写之后,您可以使用
msSet.removeAll(oracleList);
然后,如果msSet.isEmpty()
返回false
,您知道msSet
中的项目oracleSet
中不存在。{1}}。如果您愿意,可以通过迭代msSet
来打印它们。
当然,如果你需要保留msSet
以便在删除之前继续工作,请使用它的副本:
Set<String> copyOfMsSet = new HashSet<>( msSet );
并使用copyOfMsSet.removeAll(oracleList)
代替msSet.removeAll(oracleList)
。
HashSet
搜索效率非常高。如果你这样做,你应该使用TreeSet
,但效率会降低。请注意,效率取决于设置的容量和负载系数(可以在构造函数中设置),这可能会影响非常大的集合的性能。
如果oracleSet
比msSet
大得多,那么做这样的事情会更有效率:
Set <String> intersectionOfMsAndOracleSets = new HashSet<>( msSet );
intersectionOfMsAndOracleSets.retainAll( oracleSet );
然后
msSet.removeAll( intersectionOfMsAndOracleSets );
也就是说,假设msSet
的大小为n
且oracleSet
的大小为m
,n
远小于m
然后交集的操作需要O(n),而我的原始建议是O(m)。如果m
大约是n
的四倍,则会变得更有效率。
答案 1 :(得分:2)
你最大的问题是contains()
是O(n),因为它只是遍历列表直到它被命中(平均迭代次数为n / 2),这当然表现不佳。
此外,对列表进行排序对性能没有任何帮助。
卑微的HashSet
是你的朋友:它具有O(1)所有操作的表现。
使用集合还可以在几行中完成所有操作:
Set<String> set = new HashSet<>(oracleSQLList);
for (String s : MsSQLList)
if (!set.contains(s))
logger.debug(" *[POSSIBLE MISS]* Oracle missing record id: " + s);
上述代码应该在几分之一秒内完成。
答案 2 :(得分:1)
因为你有你的列表排序,你可以做二次复杂度,你可以使用线性方法
for (int i=0,j=0;i<MsSQLList.size();i++){
if (j>=oracleSQLList.size() || !MsSQLList.get(i).equals(oracleSQLList.get(j))){
logger.debug(" *[POSSIBLE MISS]* Oracle missing record id: "
+ (MsSQLList.get(index)));
}else{
j++;
}
}
但同样,你的瓶颈将是排序,除非你能在数据库中做到这一点