![](/img/trans.png)
[英]How to check if ArrayList<ArrayList<String>> contains a certain ArrayList<String>
[英]How much faster will a .contains() method be for a Hashtable<ArrayList<String>,boolean> than an ArrayList<ArrayList<String>>?
我基本上是在做以下事情:
ArrayList< ArrayList< String>>
。 对另一个数据库表执行相同的操作。
通过遍历第二个数据库并执行a.contains(b.get(i))
来a.contains(b.get(i))
第二个数据库中第一个数据库中的所有行ArrayList< String>
。 如果包含为true
则执行a.remove(b.get(i))
现在,如果我改为使用Hashtable <Arraylist <String >>而不是上面使用a.containsKey(i.getKey())
提到的ArrayList的速度要快多少,其中i是b上的迭代器,然后使用i删除。去掉 ? 进行更改是否足够好?
另外,使用Hashmap会更谨慎吗? 如果是这样,为什么...
我的自下而上的答案:
Hashtable和HashMap之间的区别已经(彻底) 在HashMap和Hashtable之间的区别中进行了讨论。 。 简短摘要:HashMap效率更高,应该代替Hashtable使用。
在哈希数据结构(contains()和remove()操作)中查找数据的顺序为O(log2)-也就是说,它与结构中数据点数量的2对数成正比。 如果有4个数据元素,则需要X的时间。 如果有8个元素,则需要2倍的时间,16个元素和3倍的时间,依此类推。 哈希结构的数据访问时间增长非常缓慢。
在列表中查找数据的顺序为O(N)-即与列表中元素的数量成正比。 1个元素花费Y时间,2个元素花费2Y时间,4个元素花费4Y时间,依此类推。 因此,时间消耗随列表的大小线性增长。
因此:如果必须从数据结构中随机查找大量元素,则哈希数据结构是最佳选择,只要:
-数据具有不错的hashCode()实现(用于ArrayList的实现是可以的)
-数据具有彼此匹配的hashCode()和equals()实现,即。 如果a.equals(b),则a.hashCode()== b.hashCode()。 对于ArrayList也是如此。
另一方面,如果您正在使用有序数据,则可以使用其他算法来减少搜索并显着减少时间。 如果数据库中的数据已建立索引,则在提取数据时可能值得使用ORDER BY,然后对有序数据使用算法。
总结一下:使用HashMap代替ArrayList作为列表a。
我编写了一个小程序来对问题进行基准测试。 结果优先:程序在Core i5 2.40 GHz CPU上的Windows 7(32位)的Sun JVM 1.6.0_41上运行。 打印:
For 1000 words: List: 1 ms, Map: 2 ms
For 5000 words: List: 15 ms, Map: 12 ms
For 10000 words: List: 57 ms, Map: 12 ms
For 20000 words: List: 217 ms, Map: 37 ms
For 30000 words: List: 485 ms, Map: 45 ms
For 50000 words: List: 1365 ms, Map: 61 ms
在这样的简单测试中,性能特征很好地展现了自己。 我使用更多数据运行了地图版本,并得到了以下内容:
For 100000 words: List: - ms, Map: 166 ms
For 500000 words: List: - ms, Map: 1130 ms
For 1000000 words: List: - ms, Map: 3540 ms
最后是基准代码:
public void benchmarkListVersusMap() {
for (int count : new int[]{1000, 5000, 10000, 20000, 30000, 50000}) {
// Generate random sample data
List<List<String>> words = generateData(count, 10, count);
// Create ArrayList
List<List<String>> list = new ArrayList<List<String>>();
list.addAll(words);
// Create HashMap
Map<List<String>, Boolean> map = new HashMap<List<String>, Boolean>();
for (List<String> row : words) {
map.put(row, true);
}
// Measure:
long timer = System.currentTimeMillis();
for (List<String> row: words) {
if (list.contains(row)) {
list.remove(row);
}
}
long listTime = System.currentTimeMillis() - timer;
timer = System.currentTimeMillis();
for (List<String> row : words) {
if (map.containsKey(row)) {
map.remove(row);
}
}
long mapTime = System.currentTimeMillis() - timer;
System.out.printf("For %s words: List: %s ms, Map: %s ms\n", count, listTime, mapTime);
}
}
private List<List<String>> generateData(int rows, int cols, int noOfDifferentWords) {
List<List<String>> list = new ArrayList<List<String>>(rows);
List<String> dictionary = generateRandomWords(noOfDifferentWords);
Random rnd = new Random();
for (int row = 0; row < rows; row++) {
List<String> l2 = new ArrayList<String>(cols);
for (int col = 0; col < cols; col++) {
l2.add(dictionary.get(rnd.nextInt(noOfDifferentWords)));
}
list.add(l2);
}
return list;
}
private static final String CHARS = "abcdefghijklmnopqrstuvwxyz0123456789";
private List<String> generateRandomWords(int count) {
Random rnd = new Random();
List<String> list = new ArrayList<String>(count);
while (list.size() < count) {
StringBuilder sb = new StringBuilder(20);
for (int i = 0; i < 10; i++) {
sb.append(CHARS.charAt(rnd.nextInt(CHARS.length())));
}
list.add(sb.toString());
}
return list;
}
size isEmpty,get,set,iterator和listIterator操作在恒定时间内运行。 加法运算以固定的固定时间运行,也就是说,添加n个元素需要O(n)时间。 所有其他操作均以线性时间运行(大致而言)。 与LinkedList实现相比,常数因子较低。
这意味着,第二个列表上的get操作在恒定时间O(1)上运行,从性能角度来看应该可以。 但是contains和remove操作(在第一个列表上)在线性时间O(n)中运行。 以第二个列表的大小多次调用这些操作可能会持续很长时间,尤其是在两个列表都很大的情况下。
对于第一个使用哈希数据结构将导致恒定的时间-O(1)-调用操作包含和删除。 我建议对第一个“列表”使用HashSet。 但这仅在所有行都不相等的情况下有效。
但是,在尝试优化某些东西之前,您应该始终进行概要分析。 首先,请确保您在正确的位置进行优化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.