我需要创建电话簿类的东西。它包含名称和数。现在当我键入字母时,应该返回匹配列表。对于下面给出的示例,当我键入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");
任何想法如何实现它? 提前致谢。
答案 0 :(得分:29)
是的,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);
}
如果您希望前缀过滤器不依赖于大小写差异,请为地图使用合适的比较器(例如Collator
具有合适的强度设置,或String.CASE_INSENSITIVE_ORDER
)。
答案 1 :(得分:9)
这需要Trie数据结构。有关java实现,请参阅this question。我使用了this one。
答案 2 :(得分:0)
将它全部放在MultiMap中(或者只是将List存储为HashMap中的值)。对于“布朗”,请存储:
"B"->["Brown"]
"BR"->["Brown"]
"BRO"->["Brown"]
如果您以后添加“Bradley”:
"B"->["Brown", "Bradley"]
"BR"->["Brown", "Bradley"]
"BRO"->["Brown"]
"BRA"->["Bradley"]
等...
然后有另一张地图将“Brown”或“Bradley”映射到电话号码。
答案 3 :(得分:0)
删除所有不包含关键部分的值:
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()));
答案 4 :(得分:-1)
使用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+"]";
}
}