通过哈希表的一部分键获取值

时间:2010-06-10 13:01:17

标签: java hashtable

说我有Hashtable<String, Object>这样的键和值:

apple => 1
orange => 2
mossberg => 3

我可以使用标准get方法通过“apple”获得1,但我想要的是通过键的一部分获得相同的值(或值列表),例如“ppl” 。当然,它可能会产生几个结果,在这种情况下,我希望能够处理每个键值对。所以基本上类似于LIKE '%ppl%' SQL语句,但我不想仅仅因为我不想添加不必要的复杂性而使用(内存中)数据库。你会推荐什么?

更新 不需要在Hashtable中存储数据。我正在寻找一种解决这个问题的通用方法。

8 个答案:

答案 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 guava
public 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(答案二)