Búsqueda parcial en HashMap


Necesito crear una guía telefónica. Contiene nombre y número. Ahora, cuando escribo letras que coinciden con la lista debe ser devuelto. Para el ejemplo dado a continuación, cuando escribo H, una lista que contiene Harmer, Harris, Hawken, Hosler debe ser devuelta. Cuando el tipo Ha entonces la lista que contiene solamente Harmer, Harris, Hawken debe ser devuelta.

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

¿Alguna idea de cómo lograrlo? Gracias de antemano.

Author: Paŭlo Ebermann, 2011-07-16

4 answers

Sí, un HashMap no es la estructura de datos correcta para esto. Como dijo Bozho, un Trie sería el correcto.

Con las herramientas integradas de Java, se podría usar un mapa de árbol (o cualquier SortedMap, en realidad):

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 salida incluso se ordenaría por clave.

Aquí un ejemplo de uso:

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 desea que su filtro de prefijo no dependa de las diferencias de mayúsculas y minúsculas, utilice un comparador adecuado para su mapa (como un Collator con un ajuste de fuerza adecuado, o String.CASE_INSENSITIVE_ORDER).

 29
Author: Paŭlo Ebermann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-18 21:17:14

Esto requiere una estructura de datos Trie. Vea esta pregunta para implementaciones de java. Usé este.

 9
Author: Bozho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:56

Ponlo todo en un MultiMap (o simplemente almacena una Lista como el valor en tu HashMap). Para" Marrón", almacenar:

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

Si luego agrega "Bradley":

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

Etc...

Luego tenga otro mapa para mapear "Brown" o "Bradley" al número de teléfono.

 0
Author: dgrant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-15 21:52:59

Use guava Multimap facilitará su solución.

La clave es la primera letra del nombre, el valor es un Collection que contiene todo el par nombre-teléfono cuyo nombre se inicia con la clave(primera letra).

Ejemplo:

    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+"]";
      }

}

 -1
Author: 卢声远 Shengyuan Lu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-16 02:52:46