有效地搜索可比较对象的Java集合

有效地搜索可比较对象的Java集合,java,algorithm,search,treemap,comparable,Java,Algorithm,Search,Treemap,Comparable,我有一个Java 8应用程序,它有一个任意的映射,其中T扩展了可比的 最简单的示例使用整数: Map<Integer,String> numbers = new HashMap<>(4); numbers.put(10,"value10"); numbers.put(20,"value20"); numbers.put(30,"value30"); numbers.put(40,"value40"); Map number=新的HashMap(4); 数字。投入(10,

我有一个Java 8应用程序,它有一个任意的
映射
,其中T扩展了
可比的

最简单的示例使用整数:

Map<Integer,String> numbers = new HashMap<>(4);
numbers.put(10,"value10");
numbers.put(20,"value20");
numbers.put(30,"value30");
numbers.put(40,"value40");
Map number=新的HashMap(4);
数字。投入(10,“价值10”);
数字。投入(20,“价值20”);
数字。投入(30,“价值30”);
数字。投入(40,“价值40”);
我想在这个映射中搜索接近任意输入值的键,向上取整,除非不存在更大的键,然后向下取整。例如:

  • input-5返回键10(四舍五入到大于input的最小键)
  • 输入8返回键10(四舍五入到大于输入的最小键)
  • 输入10返回键10(精确匹配)
  • 输入11返回键20(四舍五入到大于输入的最小键)
  • 输入40返回键40(精确匹配)
  • 输入100返回键40(向下舍入,不存在大于10的键)
我有一个工作的实现,它天真地循环所有键,进行所有必要的比较,并根据这些标准返回最佳匹配键。我的应用程序需要经常检查同一个映射中的不同值,因此这种简单的查找可能会成为瓶颈。如中所示,我相信排序树映射可能会显著增加查找时间,但是如果没有一些指导,这个类对我来说有点太复杂了

  • 我可以使用树映射的哪些方法来实现此查找
  • 下面的algorhitm如何利用树形图被排序的优势来简化
  • 如果不是TreeMap,那么另一种数据结构是否更适合这种情况
这是一个幼稚(但有效)的实现。集合实际上是地图的键集:

private T getBestMatchingKeyForValue(Collection<T> keys, T value)
{
    T bestMatchingKeySoFar = null;

    for (T keyToCheck : keys)
    {
        if (bestMatchingKeySoFar == null)
        {
            bestMatchingKeySoFar = keyToCheck;
        }
        else
        {
            int valueComparedToBestMatching = value.compareTo(bestMatchingKeySoFar);
            int valueComparedToKeyToCheck = value.compareTo(keyToCheck);
            int partitionTocheckComparedToBestMatching = keyToCheck.compareTo(bestMatchingKeySoFar);

            int signValueComparedToBestMatching = Integer.signum(valueComparedToBestMatching);
            int signValueComparedToKeyToCheck = Integer.signum(valueComparedToKeyToCheck);
            int signKeyToCheckComparedToBestMatching = Integer.signum(partitionTocheckComparedToBestMatching);

            if (signValueComparedToBestMatching == signValueComparedToKeyToCheck)
            {
                if (signValueComparedToBestMatching == signKeyToCheckComparedToBestMatching)
                {
                    bestMatchingKeySoFar = keyToCheck;
                }
            }
            else if (valueComparedToKeyToCheck == 0)
            {
                bestMatchingKeySoFar = keyToCheck;
            }
            else if (valueComparedToBestMatching != 0)
            {
                if ((this.preferUpperBound && partitionTocheckComparedToBestMatching > 0)
                        || (!this.preferUpperBound && partitionTocheckComparedToBestMatching < 0))
                {
                    bestMatchingKeySoFar = keyToCheck;
                }
            }
        }
    }

    return bestMatchingKeySoFar;
}
private T getBestMatchingKeyForValue(集合键,T值)
{
T bestMatchingKeySoFar=null;
用于(T键检查:键)
{
if(bestMatchingKeySoFar==null)
{
bestMatchingKeySoFar=keyToCheck;
}
其他的
{
int-valueComparedToBestMatching=value.compareTo(最佳匹配键OFAR);
int-valueComparedToKeyToCheck=value.compareTo(keyToCheck);
int partitionTocheckComparedToBestMatching=keyToCheck.compareTo(最佳匹配keysofar);
int-signValueComparedToBestMatching=Integer.signum(valueComparedToBestMatching);
int-signValueComparedToKeyToCheck=Integer.signum(valueComparedToKeyToCheck);
int signkey tocheckcomparedtobestmatching=Integer.signum(分区tocheckcomparedtobestmatching);
如果(SignValueComparedTobesMatching==signValueComparedToKeyToCheck)
{
if(SignValueComparedToBestMatch==SignKeyToCheckComparedToBestMatch)
{
bestMatchingKeySoFar=keyToCheck;
}
}
else if(ValueComparedTokeyTokeCheck==0)
{
bestMatchingKeySoFar=keyToCheck;
}
else if(ValueComparedTobestMatch!=0)
{
if((this.preferUpperBound&&partitionTocheckComparedToBestMatching>0)
||(!this.preferUpperBound&&partitiontocheckComparedToBestMatch<0))
{
bestMatchingKeySoFar=keyToCheck;
}
}
}
}
返回最佳匹配键OFAR;
}

TreeMap
的地板和天花板方法完全符合您的要求:

TreeMap<K, V> map = ...
K search = ...
K closest = map.ceilingKey(search);
if (closest == null) {
    closest = map.floorKey(search);
}
TreeMap映射=。。。
K搜索=。。。
K最近=map.ceilingKey(搜索);
if(最接近==null){
最近=地图楼层(搜索);
}

TreeMap
的地板和天花板方法完全符合您的要求:

TreeMap<K, V> map = ...
K search = ...
K closest = map.ceilingKey(search);
if (closest == null) {
    closest = map.floorKey(search);
}
TreeMap映射=。。。
K搜索=。。。
K最近=map.ceilingKey(搜索);
if(最接近==null){
最近=地图楼层(搜索);
}

我假设已经实现可比较(例如枚举、整数和字符串)的类在树映射中插入和排序时使用该排序,这是否正确?我如何才能偏离这种逻辑(例如,让一个枚举按名称而不是顺序按字母顺序排序?@user1884155查看树映射文档。它告诉你,假设已经实现可比较的类(例如枚举、整数和字符串)在树映射中插入和排序时使用该排序,我的假设是否正确?我如何才能偏离这种逻辑(例如,让一个枚举按名称而不是顺序按字母顺序排序?@user1884155查看树映射文档。它告诉你你看了吗?@DavidConrad实际上为我看了NavigableMap(见接受答案使用的方法)和SortedMap文档中的相关部分。你看了吗?@DavidConrad实际上为我看了NavigableMap(见接受答案使用的方法)和SortedMap文档中的相关部分。