wake-up-neo.com

Teilweise Suche in HashMap

Ich muss so etwas wie ein Telefonbuch erstellen. Es enthält Name und Nummer. Jetzt, wenn ich Buchstaben tippe, sollte zusammenpassende Liste zurückgebracht werden. Wenn ich im folgenden Beispiel H eingebe, sollte eine Liste mit Harmer, Harris, Hawken und Hosler zurückgegeben werden. Wenn Sie Ha eingeben, sollte eine Liste, die nur Harmer, Harris und Hawken enthält, zurückgegeben werden.

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

Irgendeine Idee, wie man es erreicht? Danke im Voraus.

25
Partha

Ja, eine HashMap ist dafür nicht die richtige Datenstruktur. Wie Bozho sagte, wäre ein Trie der richtige.

Mit den On-Board-Tools von Java kann eine TreeMap (oder eine beliebige SortedMap ) verwendet werden:

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

Die Ausgabe wäre sogar nach Schlüsseln sortiert.

Hier ein Anwendungsbeispiel:

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

Wenn Sie möchten, dass Ihr Präfixfilter nicht von Groß- und Kleinschreibung abhängt, verwenden Sie einen geeigneten Komparator für Ihre Karte (z. B. eine Collator mit einer geeigneten Stärkeeinstellung oder einen String.CASE_INSENSITIVE_ORDER).

29
Paŭlo Ebermann

Dies erfordert eine Trie Datenstruktur. Siehe diese Frage für Java-Implementierungen. Ich habe diesen benutzt.

9
Bozho

Entfernen Sie alle Werte, die keinen Schlüsselteil enthalten:

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

Oder Regex:

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

Oder filtern Sie Streams und sammeln Sie sie auf einer neuen Karte:

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

Fügen Sie alles in eine MultiMap ein (oder speichern Sie einfach eine Liste als Wert in Ihrer HashMap). Für "Brown" speichern Sie:

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

Wenn Sie später "Bradley" hinzufügen:

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

usw...

habe dann eine andere Karte, um "Brown" oder "Bradley" der Telefonnummer zuzuordnen.

0
dgrant