繁体   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