簡體   English   中英

在存儲桶中查找編號最快的方法是什么?

[英]What is the fastest way to lookup number in a bucket?

假設有5個存儲桶,每個存儲桶由一個對象表示,那么使用Java 8查找給定編號屬於哪個存儲桶的最快方法是什么?

例如:

List <Bucket> listOfBuckets = new ArrayList<>();

每個Bucket對象具有以下屬性

"Buckets": [{
    "bucketName":"bucket1",
    "lowerBound":0,
    "upperBound":10
}, {
    "bucketName":"bucket2",
    "lowerBound":11,
    "upperBound":20
}, {
    "bucketName":"bucket3",
    "lowerBound":21,
    "upperBound":30
}]

對於{2,15,18,14,22}中的每個,找到相應的存儲桶。

一種方法是遍歷每個數字的列表,但是如果您正在檢查存儲桶中是否有龐大的數字列表,則這將成為一項開銷。

僅作記錄, java提供了內部使用存儲桶的各種Map實現 (例如HashMap )。 HashMap使用Java hashCode在內部將它們排列在存儲桶中。 另外,還有其他具有其他屬性的地圖( LinkedHashMapConcurrentHashMap ,...)

甚至有標准的Java映射都不需要鍵的完全匹配 它們實現了NavigableMap接口。 (例如TreeMap

或者,(例如出於教育目的)如果您要從頭開始開發,我將使用基於二進制搜索的算法或索引。

您可以應用“對分法”“二進制搜索算法” (另一方面,簡單的迭代稱為“線性搜索算法” )。 二進制搜索將比線性搜索更有效,尤其是對於大型館藏。

二進制搜索假定您的元素排列良好。 然后,從嘗試中心元素開始( index = length/2 )。 如果索引包含正確的存儲桶,則可以立即退出。 如果不是,則將索引的中心放在左側或右側。 重復直到找到為止。

在代碼中:

if (bucket[index].startId > requiredId) index = index + (length-index)/2;
else if (bucket[index].stopId < requiredId) index = index - (length-index)/2;
else return bucket[index];

圖表:下圖顯示了如何使用此算法在數字列表中搜索數字7:

搜索步驟

另外(或另外),您可以在其頂部添加第二個(或第三個)存儲桶層(如索引)。 (這也是一些數據庫索引的工作方式 )。 您的結構可能如下所示:

               bucket[1-70]
               /          \
            bucket[1-25]   bucket[25-70]
           /           \            ...
         bucket[1-15]  bucket[15-25]
          ...              ...

編輯:

目前尚未訂購您的收藏。 如果您打算編寫自己的算法,那么我會先解決它。 您可以簡單地通過用TreeSet替換ArrayList來做到這一點。 每次添加元素時, TreeSet已經對元素進行TreeSet 但是有一個要求: 您的Bucket類需要實現Comparable接口和equals方法。

如果您的存儲桶遵循上述示例中所示的模式,則可以編寫如下的實用方法:

private int getBucketIndex(int number) {
    if(number between 0-10) return 0;
    if(number between 11-20) return 1;
    /*etc*/
}

public Bucket getBucket(int number) {
    return list.get(getBucketIndex(number));
}

您是否要為此專門使用Java 8?

list.stream()
    .map(n -> listOfBuckets.stream()
                            // Get rid of non-fitting buckets
                           .filter(b -> n >= b.lowerBound && n <= b.upperBound)
                           // Take the first fitting bucket found
                           .findFirst()
                           // No matching bucket? Throws NoSuchElementException 
                           .get()) 
    .collect(Collectors.toList())

請注意,無論如何,您都必須迭代列表,因此存儲桶搜索將至少受到O(n)的限制。 因為存儲桶的列表是常量(5),所以此搜索為O(5n),這意味着執行時間無論如何都呈線性增長。

如果您有可變數量的存儲桶(例如m),則線性搜索為O(m),搜索將為O(n * m)或O(n 2 ),這意味着執行時間隨着數量的增加而呈拋物線增長。更多的水桶。 此時,您應該考慮使用價格較低的數據結構,例如樹。 這將使正確的桶的搜索時間達到O(log m),總搜索將變為O(n log m),即對數增長,這比拋物線增長好得多。

暫無
暫無

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

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