繁体   English   中英

.contains()方法对Hashtable的速度将有多快 <ArrayList<String> ,boolean&gt;比ArrayList <ArrayList<String> &gt;?

[英]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;
}

ArrayListJavadoc注释摘录:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM