假设有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}中的每一个,找到相应的桶。
虽然一种方法是遍历列表中的每个数字,但如果您要检查存储桶中是否存在大量数字,这将成为开销。
答案 0 :(得分:2)
仅为了记录, java提供了广泛的Map
实现(例如HashMap
),它们在内部使用存储桶。 HashMap
使用java hashCode
在内部将它们排列在存储桶中。或者,还有其他地图包含其他属性(LinkedHashMap
,ConcurrentHashMap
,...)
甚至还有标准的java地图,不需要与密钥完全匹配。他们实现了NavigableMap
接口。 (例如TreeMap
)
或者,(例如出于教育目的)如果你要从头开发这个,我会使用基于二进制搜索的算法或索引。
您可以应用"Bisection method"或"Binary search algorithm"。 (另一方面,简单的迭代称为"Linear search algorithm")。 二进制搜索比线性搜索更有效,特别是对于大型集合。
二进制搜索假定您的元素排序很好。然后,您首先尝试中心元素(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:
或者(或另外),你可以在它上面添加第二个(或第三个)存储桶(如索引)。(这也是how some database indexes work)。您的结构可能如下所示:
bucket[1-70]
/ \
bucket[1-25] bucket[25-70]
/ \ ...
bucket[1-15] bucket[15-25]
... ...
修改强>
目前没有订购您的收藏品。如果你打算编写自己的算法,那么我会先修复它。您只需将ArrayList
替换为TreeSet
即可。 每次添加元素时,TreeSet
都已对您的元素进行排序。但是有一个要求:您的Bucket
类需要实现Comparable
接口和equals
方法。
答案 1 :(得分:1)
如果您的存储桶遵循上面示例中所示的模式,那么您可以编写如下的实用程序方法:
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));
}
答案 2 :(得分:1)
你想特别使用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)或对数增长,这比抛物线增长要好得多。