【问题标题】:Get values for keys within a range in Java获取Java中某个范围内的键的值
【发布时间】:2011-03-31 23:58:23
【问题描述】:

假设我有一张 Java 地图,如下所示:

{ 
 39:"39 to 41",
 41:"41 to 43",
 43:"43 to 45",
 45:">=45"
}

如果键按排序顺序(使用树图或链接哈希图)。现在如果我尝试获取 >=39 和

【问题讨论】:

标签: java map range-map


【解决方案1】:

看起来你想要的不仅仅是SortedMap;你想要一个NavigableMap!具体可以使用floorKey操作。

这是一个例子:

    NavigableMap<Integer,String> map =
        new TreeMap<Integer, String>();

    map.put(0, "Kid");
    map.put(11, "Teens");
    map.put(20, "Twenties");
    map.put(30, "Thirties");
    map.put(40, "Forties");
    map.put(50, "Senior");
    map.put(100, "OMG OMG OMG!");

    System.out.println(map.get(map.floorKey(13)));     // Teens
    System.out.println(map.get(map.floorKey(29)));     // Twenties
    System.out.println(map.get(map.floorKey(30)));     // Thirties
    System.out.println(map.floorEntry(42).getValue()); // Forties
    System.out.println(map.get(map.floorKey(666)));    // OMG OMG OMG!

请注意,还有 ceilingKeylowerKeyhigherKey…Entry 而不是 …Key 操作以及返回 Map.Entry&lt;K,V&gt; 而不仅仅是 K

【讨论】:

  • 我不知道这一点,显然这里也没有人知道。很酷!
  • 欢迎标准运行时!
  • 有时我觉得我知道 Java,然后我遇到这样的事情,我的思绪被震撼了。
【解决方案2】:

试试 Java 6 java.util.NavigableMaphttp://download.oracle.com/javase/6/docs/api/java/util/NavigableMap.html.

特殊用途floorKey/floorEntry

例如:floorKey(40) 应该返回 39。 floorEntry 将返回您要查找的值。

【讨论】:

    【解决方案3】:

    使用排序地图,您可以执行以下操作:

    SortedMap<Integer,String> head = map.headMap(value+1);
    if (head.isEmpty()) {
        return null;
    } else {
        return head.get(head.lastKey());
    }
    

    【讨论】:

      【解决方案4】:

      我不确定这是否容易。一个建议是“填补空白”,即输入一个值40-&gt;"39 to 41" 等。我想这只有在您知道地图中可能存在的整个数字范围的情况下才有可能。

      或者可能是覆盖get 的东西以检查该值是否在地图中,并展开直到找到某些东西。我不确定在目前的情况下这是否可行,因为您最终必须解析值字符串。

      【讨论】:

        【解决方案5】:

        您可以递归地寻找下边界。

        public String descriptionFor(int value) {
            String description = map.get(value);
            return description == null ? descriptionFor(value--) : description;
        }
        

        您需要有一个最小边界。

        【讨论】:

          【解决方案6】:

          我相信你必须自己实现这样的地图。您是对的,必须对其进行排序; get 的实现必须遍历键,直到找到小于或等于参数的最大键。

          如果您将TreeMap 子类化,最初看起来您可以通过简单地覆盖get() 方法来使其工作。但是,为了尽可能多地维护 Map 契约,您必须重写其他方法以保持一致性。

          然后呢? containsKey()?您的 main 是否包含40 的映射?如果您返回false,则客户端可以根据此信息决定不调用get();由于这些原因(以及正式定义),您必须返回true。但是,很难确定映射是否“真正包含”给定映射;如果您希望在不覆盖任何已经存在的情况下执行更新等操作。

          remove() 方法也可能很棘手。根据我对界面的阅读,

          // Calling map.remove "Removes the mapping for a key from this map if it is present."
          map.remove(x);
          
          // Now that the mapping is removed, I believe the following must hold
          assert map.get(x) == null;
          assert map.containsKey(x);
          

          在这里始终如一地行事会非常棘手。例如,如果您有一个从 35 到 40 的映射,并且您调用 remove(38),那么据我所知,您必须为键 38 的任何后续获取返回 null,但返回键 35 的上述映射-37 或 39-40。


          因此,虽然您可以通过覆盖 TreeMap 来开始此操作,但 Map 的整个概念可能并不是您想要的。除非您需要将此行为插入到采用 Map 的现有方法中,否则您自己将其创建为一个独特的类可能会更容易,因为它不是 相当 一个 Map,就像您定义它的方式一样。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-08-25
            • 1970-01-01
            • 1970-01-01
            • 2017-07-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多