2010-05-05 28 views

Respuesta

32

Puede usar el estándar Collections#min() para esto.

Map<String, Double> map = new HashMap<String, Double>(); 
map.put("1.1", 1.1); 
map.put("0.1", 0.1); 
map.put("2.1", 2.1); 

Double min = Collections.min(map.values()); 
System.out.println(min); // 0.1 

actualización: ya que se necesita la llave, así, así, no veo formas en Collections o Google Collections2 API desde una Map no es un Collection. El Maps#filterEntries() tampoco es realmente útil, ya que solo conoce el resultado real en final de iteración.

La solución más sencilla sería entonces la siguiente:

Entry<String, Double> min = null; 
for (Entry<String, Double> entry : map.entrySet()) { 
    if (min == null || min.getValue() > entry.getValue()) { 
     min = entry; 
    } 
} 

System.out.println(min.getKey()); // 0.1 

(nullcheck en min dejó a un lado)

+0

Gracias por la respuesta - Olvidé mencionar que necesito la clave del valor mínimo – user326667

+0

Muchas gracias, por cierto, también tendría que obtener los rangos de un mapa ordenado. Me gustaría usar el índice como rango (1,2,3 ...) ¿Cuál podría ser la mejor manera de hacer esto con los mapas ya que aquí no es posible obtener el índice? Es bastante inconviniente crear una lista del mapa cada vez – user326667

+1

Si desea un índice, realmente necesitará usar una 'Lista ' en su lugar en combinación con un 'Comparador 'adecuado o quizás' Comparable '. El 'SomeObject' a su vez puede mantener la clave y el valor del mapa original. Un 'Set ' también puede ser adecuado, usted solo contará el índice usted mismo. – BalusC

4

En forma tradicional, tendría que tipo el mapa de acuerdo a los valores, y toma el primero/último. gracias

No, no lo haría. Tendría que repetir todos los valores y en cada paso comparar el elemento actual con el más pequeño visto hasta ahora. Eso es O (n), en comparación con O (n * log (n)) para la clasificación - una diferencia potencialmente enorme diferencia.

Por cierto, así es exactamente como funciona Collections.min().

+0

Si ordeno el mapa según los valores, obtengo un nuevo mapa ordenado, por ejemplo: (A, 1), (B, 2), (C, 3) Aquí, puedo tomar solo la clave del primer elemento. – user326667

+0

¿Qué hay de malo en este enfoque? – user326667

+0

@ chris-gr: lleva mucho más tiempo y utiliza más memoria de la necesaria. –

1

Para hacerlo de manera eficiente, es posible que desee definir su propia estructura de datos, de modo que implemente la interfaz de Mapa, pero también permita la operación eficiente de getMin().

Esto se puede hacer usando dos estructuras de datos internas: un mapa y un árbol (o estructura de datos de montón). Cada vez que se agrega un nuevo par (K, V), agréguelos al mapa, y también al árbol (como una sola entrada). Esto permite O (1) tiempo para las operaciones get (Key) y O (log n) para las operaciones add, remover y getMin.

+0

Gracias por todos sus comentarios – user326667

2

Me inclinaría a usar un Google Colecciones BIMAP:

 String minKey = HashBiMap.create(map).inverse().get(Collections.min(map.values())); 

O algo por el estilo (no probado).

+0

Bonito delineador de ojos, pero no muy eficiente. – BalusC

+0

Pero puede ser que los valores sean del mismo valor (doble) ¿Qué clave obtengo en este caso? – user326667

+0

@chris, tiene que ver con cuál es la clave y cuál es el valor en el mapa, no sus tipos. Al final, en tiempo de ejecución, todos son Object de todos modos. – Yishai

14

Puede seguir utilizando Collections.min con una costumbre Comparator para obtener el Map.Entry con el valor más bajo:

Map<String, Double> map = new HashMap<String, Double>(); 
map.put("1.1", 1.1); 
map.put("0.1", 0.1); 
map.put("2.1", 2.1); 
Entry<String, Double> min = Collections.min(map.entrySet(), new Comparator<Entry<String, Double>>() { 
    public int compare(Entry<String, Double> entry1, Entry<String, Double> entry2) { 
     return entry1.getValue().compareTo(entry2.getValue()); 
    } 
}); 
System.out.printf("%s: %f", min.getKey(), min.getValue()); // 0.1: 0.100000 

Con Java 8:

Entry<String, Double> min = Collections.min(map.entrySet(), 
             Comparator.comparing(Entry::getValue)); 
1

Utilización de Java 8 (y las importaciones estáticas).Podemos hacer una solución de @ superfav mucho más ordenado:

Map<String, Double> myMap; 
String theKeyWithHighestValue = Collections.min(myMap.entrySet(), comparingDouble(Entry::getValue)).getKey() 
2

Utilización de Java 8 corrientes:

return map 
      .entrySet() 
      .stream() 
      .sorted(Comparator.comparingDouble(Map.Entry::getValue)) 
      .findFirst() 
      .map(Map.Entry::getValue); 

O

return map 
      .entrySet() 
      .stream() 
      .min(Comparator.comparingDouble(Map.Entry::getValue)) 
      .map(Map.Entry::getValue); 

Pero si quieres hacerlo varias veces, entonces definitivamente dar heap una mirada.

Cuestiones relacionadas