问题 如何检查Map中的键是否以给定的String值开头


我正在寻找一种方法:

myMap.containsKeyStartingWith("abc"); // returns true if there's a key starting with "abc" e.g. "abcd"

要么

MapUtils.containsKeyStartingWith(myMap, "abc"); // same

我想知道是否有人知道这样做的简单方法

谢谢


10059
2018-01-25 17:40


起源



答案:


这可以用标准来完成 SortedMap

Map<String,V> tailMap = myMap.tailMap(prefix);
boolean result = (!tailMap.isEmpty() && tailMap.firstKey().startsWith(prefix));

未排序的地图(例如 HashMap)本质上不支持前缀查找,所以对于那些你必须迭代所有键。


13
2018-01-25 17:45



因为我正在使用我收集的hashmap,所以我可以通过以下方式制作树图: TreeMap treeMap = new TreeMap(); treeMap.putAll(hashMap); - Edd
@Edd:或者,甚至更简单, TreeMap<K,V> treeMap = new TreeMap<K,V>(hashMap); - NPE


答案:


这可以用标准来完成 SortedMap

Map<String,V> tailMap = myMap.tailMap(prefix);
boolean result = (!tailMap.isEmpty() && tailMap.firstKey().startsWith(prefix));

未排序的地图(例如 HashMap)本质上不支持前缀查找,所以对于那些你必须迭代所有键。


13
2018-01-25 17:45



因为我正在使用我收集的hashmap,所以我可以通过以下方式制作树图: TreeMap treeMap = new TreeMap(); treeMap.putAll(hashMap); - Edd
@Edd:或者,甚至更简单, TreeMap<K,V> treeMap = new TreeMap<K,V>(hashMap); - NPE


从地图中,您可以获得一组键,如果它们是String,您可以迭代Set的元素并检查 startsWith("abc")


2
2018-01-25 17:42



谢谢,我可以看到这会工作,虽然我希望我不必迭代通过键集 - Edd
@Edd为什么不呢?它是由java家伙优化使用这种方式;) - Adel Boutros
它导致更高的圈复杂度,除非你把它拉成一个单独的方法,我没有明确的类来放这样的方法,所以我希望我不需要为单个方法的地图创建一个新的实用程序类..听起来像我说的那样我很懒,但如果碰巧有一个现成的实用方法,那会有所帮助...一厢情愿;) - Edd
迭代映射键的效率较低:它是O(N)。有序映射可以做得更好:O(log N)。 - Martin Ellis
@martiell但他没有说明他正在使用什么样的地图 - Adel Boutros


要建立在Adel Boutros上关于迭代键效率的答案/评论,你可以将密钥迭代封装在一个 Map 子类或装饰器。

扩展 HashMap 会给你一个类来放置方法并保留你的方法中特定于地图的代码,从而降低复杂性并使代码更自然地阅读。


0
2018-01-26 12:47



这意味着我的HashMap需要是扩展HashMap的一个实例,我必须从Map执行转换(如果地图被声明为Map)以使用该方法。它确实把代码放在一个整洁的地方,但可能不会那么有用 - Edd
是。或者你可以做到 MyMapExtension m = new MyMapExtension(myMap); 或者您可以使用装饰器解决方案来包装地图。两者都会与您原来的想法相似。 - David Carboni
我明白了...我想装饰器选项会阻止创建一个新的地图实例,所以应该更有效率 - Edd