2012-01-14 25 views
5

supone que soy creado un HashMap dentro de otro HashMap como se muestra a continuación que puede almacenar el valor dentro del interior HashMap basada en la clave del exterior HashMap en el tiempo de ejecuciónAlmacenamiento de un HashMap dentro de otro HashMap y mejorar el rendimiento

es decir, la salida requerida para el programa debe tener el formato

{ 1 = {11 = "aaa",15 = "bbb"}, 2 = {13 = "ccc", 14 = "ddd"} } 

donde 1,2 son valores clave para HashMap externo.

A continuación se muestra el código proporcionado por ella ¿Hay alguna mejor enfoque para mejorar el rendimiento

HashMap<Integer, HashMap<Integer, String>>Outer 
        = new HashMap<Integer, HashMap<Integer,String>>(); 

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
    int count = Integer.parseInt(br.readLine()); 
    for(int i =0;i<count;i++) 
    { 
     String input[] = br.readLine().split("\\s"); 

     //HashMap<Integer,String>inner = new HashMap<Integer, String>(); 
     int key = Integer.parseInt(input[0]); 
     if(Outer.isEmpty() || !Outer.containsKey(key)) 
     { 
      HashMap<Integer, String> inner = new HashMap<Integer, String>(); 
      inner.put(Integer.parseInt(input[1]),input[2]); 
      Outer.put(key, inner); 
     } 
     else if(Outer.containsKey(key)) 
      { 
       HashMap<Integer, String> inner = (HashMap<Integer, String>) Outer.get(key).clone(); 
       inner.put(Integer.parseInt(input[1]), input[2]); 
       Outer.put(key, inner); 
      } 
    } 
+1

¿Por qué crees que necesitas mejorar el rendimiento? ¿Este código toma una cantidad extraordinaria de tiempo para ejecutarse? – Jeffrey

+2

Creo que usar un hashmap de dos niveles tiene más probabilidades de reducir el rendimiento que aumentarlo. –

+0

Si bien no está claro, podría suponerse a partir de la pregunta de que la división en 2 mapas no es por motivos de rendimiento. Tenga en cuenta que la determinación de qué mapa externo usar se lee de la entrada, no es otro hash calculado. Creo que la pregunta está dirigida a mejorar el rendimiento de la implementación dada, que requiere el uso de mapas anidados. – ziesemer

Respuesta

2

Similar a la respuesta de Vadim, pero aún más mejorada - ya que no requiere una llamada a la vez containsKey, así como get:

Map<Integer, Map<Integer, String>> outer = new HashMap<Integer, Map<Integer, String>>(); 
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
int count = Integer.parseInt(br.readLine()); 

Pattern splitter = Pattern.compile("\\s"); 

for(int i = 0; i < count; i++){ 
    String input[] = splitter.split(br.readLine()); 

    int key = Integer.parseInt(input[0]); 

    Map<Integer, String> inner = outer.get(key); 
    if(inner == null){ 
     inner = new HashMap<Integer, String>(); 
     outer.put(key, inner); 
    } 
    inner.put(Integer.parseInt(input[1]), input[2]); 
} 

también tiene algunas pequeñas mejoras para las convenciones de nombres, y el uso de las Interfaces de las colecciones en lugar de tipos concretos.

También eliminé la llamada al clone. Esto podría ser un ahorro leve, y no creo que le haya dado los resultados esperados.

Finalmente, otra cosa que he cambiado que podría ser una ligera mejora es utilizar un patrón precompilado para dividir su cadena en los campos.

+0

Gracias ziesemer grandes consejos para modificar – cryptonkid

0

Su código es lo suficientemente bueno desde el punto de vista del rendimiento. Solo se me ocurrieron algunas cosas. Si/condición else puede simplificarse y que no es necesario para clonar mapa en otra parte (el trabajo con el puntero)

HashMap<Integer, HashMap<Integer, String>>Outer = new HashMap<Integer, HashMap<Integer,String>>(); 
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
int count = Integer.parseInt(br.readLine()); 
for(int i =0;i<count;i++) 
{ 
    String input[] = br.readLine().split("\\s"); 

    //HashMap<Integer,String>inner = new HashMap<Integer, String>(); 
    int key = Integer.parseInt(input[0]); 
    if(!Outer.containsKey(key)) 
    { 
     HashMap<Integer, String> inner = new HashMap<Integer, String>(); 
     inner.put(Integer.parseInt(input[1]),input[2]); 
     Outer.put(key, inner); 
    } 
    else 
    { 
     HashMap<Integer, String> inner = Outer.get(key); 
     inner.put(Integer.parseInt(input[1]), input[2]); 
    } 
} 
+0

Gracias por sus consejos vadim :) Gran ayuda de hecho – cryptonkid

1

La optimización es casi siempre una mala idea. Especialmente en Java, donde la JVM es bastante buena para hacerlo por sí misma.

lo que realmente necesita un Map<Integer, Map<Integer, String>>, me parece que lo que realmente necesita un Map<Pair, String> donde

public final class Pair { 
    private final int x; 
    private final int y; 
    public Pair(int x, int y) { this.x = x; this.y = y;} 
} 

No pretendo en absoluto que esto mejorará el rendimiento, pero podría ser mejor diseño. No sé exactamente lo que estás haciendo, así que tal vez no es un mejor diseño.

+0

Tenía la corazonada de que este es el camino correcto. Así que busqué la "pregunta incorrecta" para preguntar y llegué aquí. He usado objetos con Hashmaps que luego se usan en otro objeto. No estaba seguro de si eso era una buena práctica y su respuesta ayuda a confirmar que la explotación de OOP es el camino a seguir. – Vangel

+0

@Vangel Por cierto, asegúrese de usar un objeto inmutable como clave para un mapa. El mapa utiliza el [hash] (https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode--) del objeto como la clave real. Si su objeto es mutable, cambiar el objeto probablemente cambie el hash y ya no podrá encontrar nada en el mapa. – toto2

+0

He generado hashcode y es igual para los objetos para identificar la unicidad, ¿eso ayudará? No estoy seguro de si puedo hacer algo inmutable, aunque sería ideal. – Vangel