web-dev-qa-db-ja.com

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

どのようにそれを達成するのですか?前もって感謝します。

31
Partha

ええ、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)。

29
Paŭlo Ebermann

これは、 Trie データ構造を必要とします。 Java実装については this question を参照してください。私は thisを使用しました

9
Bozho

キーパーツを含まないすべての値を削除します。

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()));
0
Justas

すべてをMultiMapに配置します(またはListを値としてHashMapに格納します)。 「ブラウン」の場合は、次を保存します。

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

後で「Bradley」を追加する場合:

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

等...

次に、「Brown」または「Bradley」を電話番号にマップする別のマップを用意します。

0
dgrant