簡體   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