web-dev-qa-db-fra.com

Recherche partielle dans HashMap

J'ai besoin de créer un genre d'annuaire téléphonique. Il contient le nom et le numéro. Maintenant, lorsque je tape des lettres, la liste correspondante doit être renvoyée. Pour l'exemple donné ci-dessous, lorsque je tape H, une liste contenant Harmer, Harris, Hawken, Hosler doit être renvoyée. Lorsque le type Ha contient une liste ne contenant que Harmer, Harris, Hawken doit être renvoyé.

  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");

Une idée comment y parvenir? Merci d'avance.

25
Partha

Oui, un HashMap n'est pas la bonne structure de données pour cela. Comme Bozho l'a dit, un Trie serait le bon.

Avec les outils embarqués de Java, une TreeMap (ou n'importe quel SortedMap , en fait) pourrait être utilisé:

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;
}

La sortie serait même triée par clé.

Voici un exemple d'utilisation:

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);
}

Si vous souhaitez que votre filtre de préfixe ne dépende pas des différences de casse, utilisez un comparateur approprié pour votre carte (par exemple, une variable Collator avec un paramètre de force approprié ou String.CASE_INSENSITIVE_ORDER).

29
Paŭlo Ebermann

Cela appelle une structure Trie data. Voir cette question pour les implémentations Java. J'ai utilisé celui-ci .

9
Bozho

Mettez tout cela dans une carte multiple (ou stockez simplement une liste en tant que valeur dans votre carte de hachage). Pour "Brown", stockez:

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

Si vous ajoutez plus tard "Bradley":

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

etc...

puis avoir une autre carte pour mapper "Brown" ou "Bradley" au numéro de téléphone.

0
dgrant