簡體   English   中英

在大型數據集中查找唯一條目的最有效方法

[英]Most efficient way to find unique entries in a large data set

在開始之前,我要明確指出這是一項作業,並且我不希望得到完整的編碼答案。 我所尋求的只是建議,或者是有助於我的代碼片段。

因此,我正在讀取大約900,000個單詞,這些單詞全部存儲在arrayList中。 我需要使用Java中的排序數組(或arraylist)來計算唯一單詞。

到目前為止,我只是循環遍歷給定的arrayList並使用

Collections.sort(words); 

Collections.binarySearch(words, wordToLook); 實現它,如下所示:

OrderedSet set = new OrderedSet();
    for(String a : words){
        if(!set.contains(a)){
            set.add(a);
        }
    }

public boolean contains(String word) {
    Collections.sort(uniqueWords);
    int result = Collections.binarySearch(uniqueWords, word);

    if(result<0){
        return false;
    }else{
        return true;
    }
}

這段代碼的運行時間大約為60秒,但是我想知道是否還有更好的方法,因為每次添加元素時運行排序效率都非常低(但是如果我要使用二進制搜索的話,這很必要)。

任何形式的反饋將不勝感激。 謝謝。

我不會使用排序數組。 我將創建一個Map<String, Integer> ,其中鍵是您的單詞,值是單詞出現次數的計數。 當您閱讀每個單詞時,請執行以下操作:

Integer count = map.get(word);
if (count == null) {
    count = 0;
}
map.put(word, count + 1);

然后,只需遍歷地圖的條目集,然后對計數進行任何處理即可。

如果您知道或可以估計唯一單詞的數量,則應在HashMap構造函數中使用此數字(這樣就不必多次擴展地圖)。

如果使用排序數組,則運行時間不能與NlogN成正比(其中N是列表中的單詞數)。 如果使用HashMap,則可以實現隨N線性增長的運行時(您節省了logN的因數)。

使用Map的另一個優勢是,所使用的內存與唯一單詞的數量成正比,而不是與單詞的總數成比例(假設您在讀取單詞時構建了Map,而不是將所有單詞都讀入一個集合然后添加它們到地圖)。

因此,您需要使用排序數組。 可以,因為您(尚未)在現實世界中編程。

我將建議兩種選擇:

第一種使用二進制搜索(您在當前代碼中使用的二進制搜索)。

我將創建一個包含兩個字段的類:單詞(字符串)和該單詞的計數(整數)。 您將構建這些類的排序數組。

從一個空數組開始,然后在閱讀每個單詞時將其添加到其中。 對於每個單詞,在要構建的數組中進行二進制搜索。 搜索將找到包含單詞的條目(您將增加計數),或者確定單詞尚未出現在數組中。

當二分查找結束而沒有找到單詞時,您將創建一個新對象來容納單詞+計數,並將其添加到搜索結束位置的數組中(請注意確保邏輯確實將其正確放置以使您的列表保持排序)。 當然,您將新單詞的計數設置為1。

另一種選擇:

將所有單詞讀入列表並進行排序。 排序后,所有重復項將在列表中彼此相鄰。

您將在此排序后的列表中查找一次,並隨即創建一個單詞+計數的列表。 如果您看到的下一個單詞與最后一個單詞+計數相同,則增加計數。 如果是新單詞,則將新單詞+計數添加到結果列表中,計數為= 1。

public static int countUnique(array) {
    if(array.length == 0) return 0;
    int count = 1;
    for i from 1 to array.length - 1 {
        if(!array[i].equals(array[i - 1])) count++;
    }
    return count;
}

這是偽代碼中的O(N)算法,用於計算已排序數組中唯一條目的數量。 其背后的想法是,我們計算相等元素組之間的過渡次數。 然后,唯一條目的數量是轉換數量加一個(對於第一個條目)。

希望您能看到對元素進行排序后如何將此算法應用於數組。

您總是可以使用比較器來獲取唯一值。

  List newList = new ArrayList(new Comparator() {
        @Override
        public int compare(words o1, words o2) {
            if(o1.equalsIgnoreCase(o2)){
                return 0;
            }
            return 1;
        }
    });

現在計數:

單詞-newList =否。 重復值。

希望這可以幫助!!!!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM