获取Java中某个范围内的键值

假设我在Java中有一个如下所示的地图:

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

如果键是按排序顺序(使用treemap或linkedhashmap)。现在,如果我尝试获得> = 39和<41的值。那么我应该得到字符串“39到41”。如何有效地执行此操作?

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

这是一个例子:

  NavigableMap map = new TreeMap(); 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而不仅仅是K

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

在特殊用途floorKey / floorEntry

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

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

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

我不确定那会很容易。 一个建议是“填补空白”,即输入值40->"39 to 41"等等。我想只有你知道地图中可能的整个数字范围才有可能。

或者mabybe覆盖了get to to to to to to the the value是否在地图中,然后展开直到它找到了什么。 我不确定它目前的forms是否可行,因为你必须最终解析值字符串。

您可以递归查找下边界。

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

您需要具有最小边界。

我相信你必须自己实施这样的地图。 你是对的,它必须被分类; get的实现必须遍历键,直到找到小于或等于参数的最大键。

如果你是TreeMap子类,那么最初看起来你可以通过简单地重写get()方法来实现它。 但是,为了保持尽可能多的Map合约,您必须覆盖其他方法以保持一致性。

那么例如containsKey()呢? 你的主要包含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,就像你定义它一样。