[英]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
在內部將它們排列在存儲桶中。 另外,還有其他具有其他屬性的地圖( LinkedHashMap
, ConcurrentHashMap
,...)
甚至有標准的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.