Existe-t-il une méthode (peut-être avec Google Collections) pour obtenir la valeur minimale d'une Map(Key, Double)
?
De manière traditionnelle, je devrais trier la carte en fonction des valeurs et prendre la première/dernière.
Vous pouvez utiliser la norme Collections#min()
pour cela.
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
Mise à jour : puisque vous avez également besoin de la clé, eh bien, je ne vois pas de moyens dans Collections
ou Google Collections2
API car un Map
n'est pas un Collection
. La Maps#filterEntries()
n'est pas non plus vraiment utile, car vous ne connaissez le résultat réel qu'à fin d'itération.
La solution la plus simple serait alors la suivante:
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 sur min
laissé de côté)
Vous pouvez toujours utiliser Collections.min
avec un Comparator
personnalisé pour obtenir le Map.Entry
avec la valeur la plus faible:
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
Avec Java 8:
Entry<String, Double> min = Collections.min(map.entrySet(),
Comparator.comparing(Entry::getValue));
De manière traditionnelle, je devrais trier la carte en fonction des valeurs et prendre la première/dernière. Merci
Non, tu ne le ferais pas. Vous devrez parcourir toutes les valeurs et comparer à chaque étape l'élément actuel avec le plus petit vu jusqu'ici. C'est O (n), comparé à O (n * log (n)) pour le tri - une différence potentiellement énorme.
BTW, c'est exactement comme cela que fonctionne Collections.min()
.
Utilisation de Java 8 flux:
return map
.entrySet()
.stream()
.sorted(Comparator.comparingDouble(Map.Entry::getValue))
.findFirst()
.map(Map.Entry::getValue);
Ou
return map
.entrySet()
.stream()
.min(Comparator.comparingDouble(Map.Entry::getValue))
.map(Map.Entry::getValue);
Mais si vous voulez le faire plusieurs fois, alors jetez un coup d'œil à heap .
Java8 One-Liner
Key key = Collections.min(map.entrySet(), Map.Entry.comparingByValue()).getKey()
Je serais enclin à utiliser un Google Collections BiMap:
String minKey = HashBiMap.create(map).inverse().get(Collections.min(map.values()));
Ou quelque chose comme ça (non testé).
Pour le faire efficacement, vous souhaiterez peut-être définir votre propre structure de données, de sorte qu'elle implémente l'interface Map, mais permette également une opération getMin () efficace.
Cela peut être fait en utilisant deux structures de données internes: une carte et un arbre (ou structure de données en tas). Chaque fois qu'une nouvelle paire (K, V) est ajoutée, ajoutez-les à la carte, ainsi qu'à l'arbre (en une seule entrée). Cela laisse O(1) temps pour les opérations get (Key) et O (log n) pour les opérations d'ajout, de suppression et getMin.
En utilisant Java 8 (et importations statiques). Nous pouvons rendre la solution de @ superfav beaucoup plus ordonnée:
Map<String, Double> myMap;
String theKeyWithHighestValue = Collections.min(myMap.entrySet(), comparingDouble(Entry::getValue)).getKey()
En Java 8 nous pouvons obtenir facilement:
Double minValue = map.entrySet().stream().min(Map.Entry.comparingByValue()).get().getValue();
Double maxValue = map.entrySet().stream().max(Map.Entry.comparingByValue()).get().getValue();