2012-06-12 22 views
10

Digamos que obtuve un Map<String, String> y quiero eliminar todas las entradas cuyo valor contiene foo. ¿Cuál es la mejor manera de hacerlo, en términos de optimización/memoria/etc.? Los cuatro syso a continuación imprimen el mismo resultado, es decir, {n2=bar}.Pase un objeto como parámetro y modifíquelo dentro del método

public static void main(String[] args) { 

    Map<String, String> in = new HashMap<String, String>(); 
    in.put("n1", "foo"); 
    in.put("n2", "bar"); 
    in.put("n3", "foobar"); 

    // 1- create a new object with the returned Map 
    Map<String, String> in1 = new HashMap<String, String>(in); 
    Map<String, String> out1 = methodThatReturns(in1); 
    System.out.println(out1); 

    // 2- overwrite the initial Map with the returned one 
    Map<String, String> in2 = new HashMap<String, String>(in); 
    in2 = methodThatReturns(in2); 
    System.out.println(in2); 

    // 3- use the clear/putAll methods 
    Map<String, String> in3 = new HashMap<String, String>(in); 
    methodThatClearsAndReadds(in3); 
    System.out.println(in3); 

    // 4- use an iterator to remove elements 
    Map<String, String> in4 = new HashMap<String, String>(in); 
    methodThatRemoves(in4); 
    System.out.println(in4); 

} 

public static Map<String, String> methodThatReturns(Map<String, String> in) { 
    Map<String, String> out = new HashMap<String, String>(); 
    for(Entry<String, String> entry : in.entrySet()) { 
     if(!entry.getValue().contains("foo")) { 
      out.put(entry.getKey(), entry.getValue()); 
     } 
    } 
    return out; 
} 

public static void methodThatClearsAndReadds(Map<String, String> in) { 
    Map<String, String> out = new HashMap<String, String>(); 
    for(Entry<String, String> entry : in.entrySet()) { 
     if(!entry.getValue().contains("foo")) { 
      out.put(entry.getKey(), entry.getValue()); 
     } 
    } 
    in.clear(); 
    in.putAll(out); 
} 

public static void methodThatRemoves(Map<String, String> in) { 
    for(Iterator<Entry<String, String>> it = in.entrySet().iterator(); it.hasNext();) { 
     if(it.next().getValue().contains("foo")) { 
      it.remove(); 
     } 
    } 
} 

Respuesta

4

La mejor manera es methodThatRemoves porque:

  1. En términos de consumo de memoria: no crea un nuevo mapa para que no añade sobrecarga de memoria.
  2. En términos de uso de la CPU: el iterador tiene O (1) complejidad para llamar a continuación o eliminar el elemento actual.
0

personalmente me gustaría ir con methodThatRemoves porque sólo se está realizando una operación de bucle y la comprobación de la igualdad "foo". Los demás lo hacen, así como la creación de mapas de objetos y las operaciones de borrar/poner mapas. Entonces claramente tienes 1 método haciendo menos.

Además, si desea reducir el uso de la memoria, es mejor que no cree un HashMap adicional solo para eliminar 1 o más entradas. Esto supone que no te importa el cálculo extra para iterar el mapa.

Si realmente quieres profundizar más, debes evaluar esto usando un generador de perfiles o algún tipo.

1

Para mí el mejor es el que tiene los Iterator - methodThatRemoves, porque no se crea un mapa intermedio y no utiliza put método.

Por cierto, el primero: methodThatReturns puede ser más rápido porque put complejidad es O (1) mientras que remove es O (n) en el peor de los casos pero usará más memoria porque tiene 2 instancias diferentes de Map.

2

La forma más eficiente methodThatRemoves, porque

  • casi no utiliza la memoria
  • no crea objetos excepto el iterador (ligero)
  • es extremadamente rápido (no utiliza ninguna consulta al mapa)

No haría una copia primero, a menos que tenga un mapa no modificable o necesite conservar el original.

+0

¿No es eso exactamente lo que hace el método que elimina? – tibtof

+0

sí, ¿cómo es esto diferente, aparte de los iguales, que no es lo que quiere de todos modos – jonasr

+0

¡Vaya! Leí la pregunta:/Eliminaré el código :) – Bohemian

Cuestiones relacionadas