查找存储桶中数字的最快方法是什么?

时间:2015-10-14 06:16:07

标签: java search

假设有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}中的每一个,找到相应的桶。

虽然一种方法是遍历列表中的每个数字,但如果您要检查存储桶中是否存在大量数字,这将成为开销。

3 个答案:

答案 0 :(得分:2)

仅为了记录, java提供了广泛的Map实现(例如HashMap),它们在内部使用存储桶。 HashMap使用java hashCode在内部将它们排列在存储桶中。或者,还有其他地图包含其他属性(LinkedHashMapConcurrentHashMap,...)

甚至还有标准的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:

searching steps

或者(或另外),你可以在它上面添加第二个(或第三个)存储桶(如索引)。(这也是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)或对数增长,这比抛物线增长要好得多。