繁体   English   中英

在HashMap中进行部分搜索

[英]Partial search in HashMap

我需要创建电话簿类的东西。 它包含姓名和号码。 现在当我键入字母时,应该返回匹配列表。 对于下面给出的示例,当我键入H时,应返回包含Harmer,Harris,Hawken,Hosler的列表。 当输入Ha然后列出只包含Harmer,Harris,Hawken的列表应该返回。

  Map<String, String> nameNum = new HashMap<String, String>();

  nameNum.put("Brown", "+1236389023");
  nameNum.put("Bob", "+1236389023");
  nameNum.put("Harmer", "+1236389023");
  nameNum.put("Harris", "+1236389023");
  nameNum.put("Hawken", "+1236389023");
  nameNum.put("Hosler", "+1236389023");

任何想法如何实现呢? 提前致谢。

是的,HashMap不是正确的数据结构。 正如Bozho所说, Trie将是正确的。

使用Java的板载工具,可以使用TreeMap(或任何SortedMap ):

public <V> SortedMap<String, V> filterPrefix(SortedMap<String,V> baseMap, String prefix) {
    if(prefix.length() > 0) {
        char nextLetter = prefix.charAt(prefix.length() -1) + 1;
        String end = prefix.substring(0, prefix.length()-1) + nextLetter;
        return baseMap.subMap(prefix, end);
    }
    return baseMap;
}

输出甚至可以按键排序。

这是一个用法示例:

SortedMap<String, String> nameNum = new TreeMap<String, String>();
// put your phone numbers

String prefix = ...;
for(Map.Entry<String,String> entry : filterPrefix(nameNum, prefix).entrySet()) {
    System.out.println(entry);
}

如果您希望前缀过滤器不依赖于大小写差异,请为您的地图使用合适的比较器(如具有合适强度设置的CollatorString.CASE_INSENSITIVE_ORDER )。

这需要Trie数据结构。 对于java实现,请参阅此问题 我用过这个

删除所有不包含关键部分的值:

yourMap.keySet().removeIf(key -> !key.contains(keyPart));

或正则表达式:

yourMap.keySet().removeIf(key -> !key.matches(".*keyPart.*"));

或者过滤流并收集到新地图:

yourMap.entrySet().stream().filter(e -> e.getKey().contains(keyPart)).collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));

将它全部放在MultiMap中(或者只将List存储为HashMap中的值)。 对于“布朗”,商店:

"B"->["Brown"]
"BR"->["Brown"]
"BRO"->["Brown"]

如果你以后添加“Bradley”:

"B"->["Brown", "Bradley"]
"BR"->["Brown", "Bradley"]
"BRO"->["Brown"]
"BRA"->["Bradley"]

等等...

然后有另一张地图将“布朗”或“布拉德利”映射到电话号码。

使用guava Multimap将简化您的解决方案。

密钥是名字的第一个字母,值是包含所有名称 - 电话对的Collection ,其名称以密钥(第一个字母)开头。

例:

    public void test(){
      //firstLetter -> list of name-phone pair
      Multimap<String, Pair> mMap =  ArrayListMultimap.create();

      put(mMap, "Brown",  "+1236389023");
      put(mMap, "Bob",    "+1236389023");
      put(mMap, "Harmer", "+1236389023");
      put(mMap, "Harris", "+1236389023");
      put(mMap, "Hawken", "+1236389023");
      put(mMap, "Hosler", "+1236389023");

      //Test
      System.out.println(mMap.get("H"));
   }

   void put(Multimap<String, Pair> mMap, String name, String phone){
      mMap.put(name.substring(0,1), new Pair(name, phone));
   }

   public static class Pair{
      String name;
      String phone;

      public Pair(String name, String phone) {
         this.name = name;
         this.phone = phone;
      }

      @Override
      public String toString() {
         return "Pair [name="+name+", phone="+phone+"]";
      }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM