[英]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.