说我有Hashtable<String, Object>
这样的键和值:
apple => 1
orange => 2
mossberg => 3
我可以使用标准get
方法通过“apple”获得1,但我想要的是通过键的一部分获得相同的值(或值列表),例如“ppl” 。当然,它可能会产生几个结果,在这种情况下,我希望能够处理每个键值对。所以基本上类似于LIKE '%ppl%'
SQL语句,但我不想仅仅因为我不想添加不必要的复杂性而使用(内存中)数据库。你会推荐什么?
更新 不需要在Hashtable中存储数据。我正在寻找一种解决这个问题的通用方法。
答案 0 :(得分:4)
明显的暴力方法是迭代映射中的键并将它们与char序列进行匹配。对于小地图来说这可能没问题,但当然它不会扩展。
这可以通过使用第二个映射来缓存搜索结果来改进。每当您收集与给定char序列匹配的键列表时,您可以将它们存储在第二个映射中,以便下次查找速度很快时。当然,如果经常更改原始地图,则更新缓存可能会变得复杂。与缓存一样,如果地图的读取频率远远超过更改,则效果最佳。
或者,如果您事先知道可能的字符序列,则可以预先生成匹配字符串列表并预填充缓存映射。
更新: Hashtable
无论如何都不推荐 - 它是同步的,因此比它应该慢得多。如果不涉及并发,最好使用HashMap
,否则使用ConcurrentHashMap
。到目前为止,后者的表现优于Hashtable
。
除此之外,我不能想到比地图更好的收集这项任务。当然,您可以尝试不同的地图实现,找到最适合您的具体情况和使用模式的地图。一般来说,它将是
Map<String, Object> fruits;
Map<String, List<String>> matchingKeys;
答案 1 :(得分:2)
并非没有明确地迭代。 Hashtable被设计成在O(1)中去(确切)key-&gt;值,仅此而已。如果您将使用大量数据进行查询操作,我建议您考虑使用数据库。您可以使用SQLite之类的嵌入式系统(请参阅SQLiteJDBC),因此无需单独的过程或安装。然后,您可以选择database indexes。
我知道没有可以有效执行此类操作的标准Java集合。
答案 2 :(得分:2)
听起来你需要一个引用你的数据的特里。 trie存储字符串并允许您按前缀搜索字符串。我不太了解Java标准库,我不知道它是否提供了一个实现,但是可以在这里找到:
http://www.cs.duke.edu/~ola/courses/cps108/fall96/joggle/trie/Trie.java
不幸的是,trie只允许你按前缀搜索。您可以通过存储每个键的每个可能后缀来解决此问题:
对于'apple',你要存储字符串
'苹果' 'pple' 'PLE' “乐” 'e' 的
这将允许您搜索密钥的每个后缀的每个前缀。
不可否认,这种“解决方案”会促使我继续寻找其他选择。
答案 3 :(得分:1)
首先,使用hashmap,而不是hashtable。
然后,您可以使用filter the map using a predicate
中的实用程序google guavapublic Collection<Object> getValues(){
Map<String,Object> filtered = Maps.filterKeys(map,new Predicate<String>(){
//predicate methods
});
return filtered.values();
}
答案 4 :(得分:0)
无法在一次操作中完成
您可能希望尝试迭代密钥并使用包含所需字符串的密钥。
答案 5 :(得分:0)
我能看到的唯一解决方案(我不是Java专家)是迭代密钥并检查与正则表达式的匹配。如果匹配,则将匹配的键值对放在将返回的哈希表中。
答案 6 :(得分:0)
如果你能以某种方式将问题减少到按前缀搜索,你可能会发现NavigableMap有帮助。
答案 7 :(得分:0)
你会感兴趣的是抛出这些问题:Fuzzy string search library in Java
另请参阅Lucene(答案二)