web-dev-qa-db-fra.com

Obtenir la valeur minimale d'une carte (clé, double)

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.

25
user326667

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é)

48
BalusC

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));
19
superfav

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().

5

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 .

4
voho

Java8 One-Liner

Key key = Collections.min(map.entrySet(), Map.Entry.comparingByValue()).getKey()
3
Ankit Sharma

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é).

2
Yishai

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.

1
Eyal Schneider

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()
1
Tarrasch

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();
1
Az.MaYo