首页 > 解决方案 > 从 TreeMap 返回相邻键

问题描述

鉴于以下情况TreeMap

Map<Double, Integer> treeMap = new TreeMap<Double, Integer>() {{. 
        put("52.1", 1);
        put("53.4", 2); 
        put("57.1", 3); 
        put("59.4", 7); 
        put("60.2", 11); 
        put("71.6", 16)}};

对于给定的双精度数,返回最接近的 n 个匹配项(在两个方向上)的最佳方法是什么?例如,n=2 和 "58.0" 将返回 53.4、57.1、59.4、60.2

标签: javadictionarytreemap

解决方案


tl;博士

new TreeMap <>(
        Map.of(
                52.1d , 1 ,
                53.4d , 2 ,
                57.1d , 3 ,
                59.4d , 7 ,
                60.2d , 11 ,
                71.6d , 16
        )
)
.floorKey( 58.0d )     // Or call `.ceilingKey( 58.0d )`

请参阅在 IdeOne.com 上实时运行的代码

57.1

NavigableMap::lowerKey/higherKey

TreeMap是一个NavigableMap

NavigableMap接口提供检索相邻键(和条目)的方法。

重复这些命令以获取尽可能多的相邻键,直到收到null.

比较键

在二读时,您似乎没有钥匙。您有一个值要与地图中的键进行比较。

在这种情况下,获取Set地图中所有键的 a。NavigableMap延伸SortedMap。所以我们可以调用SortedMap::keySet. 返回的集合按排序顺序迭代。

Set< Double > set = map.keySet() ;

做一个List,通过索引访问单个元素。

List< Double > doublesListSorted = List.of( set.toArray() ) ;  // Get un-modifiable list.

现在您可以循环排序列表以比较值。

NavigableMap::floorKey/ceilingKey

或者,正如dnault 评论的那样,我们可以要求NavigableMap比较最近匹配的键值。

  • floorKey
    返回小于或等于给定键的最大键,如果没有这样的键,则返回 null。
  • ceilingKey
    返回大于或等于给定键的最小键,如果没有这样的键,则返回 null。

示例代码

制作输入地图。我们Map.of最初使用它是因为它方便的文字语法。然后我们将该不可修改的映射提供给TreeMap. 我们在这里看到的文字输入恰好是排序的,但这无关紧要,因为TreeMap构造函数将按键排序条目。

NavigableMap < Double, Integer > map =
        new TreeMap <>(
                Map.of(
                        52.1d , 1 ,
                        53.4d , 2 ,
                        57.1d , 3 ,
                        59.4d , 7 ,
                        60.2d , 11 ,
                        71.6d , 16
                )
        );

map.toString(): {52.1=1, 53.4=2, 57.1=3, 59.4=7, 60.2=11, 71.6=16}

设置我们想要最接近匹配的目标。

Double target = 58.0d;

获取相邻的键,下一个更低,下一个更高。

Double nextLower = map.floorKey( target );
Double nextHigher = map.ceilingKey( target );

nextLower = 57.1 nextHigher = 59.4

查看在 IdeOne.com 上实时运行的代码。


笔记:

  • 正如埃里克森所评论的那样,您的双括号初始化是一种黑客行为。List.of鉴于此答案中显示的新文字语法,现在没有必要了。
  • 如果您关心准确性,请使用BigDecimal而不是Double.

Java 11 中的地图实现表,比较它们的特性


推荐阅读