Ma

Maps en Java

11 exercices

À propos de Maps

Une Map est une structure de données qui permet de stocker des paires clé-valeur. Elle est similaire aux dictionnaires d'autres langages de programmation. L'interface Map définit les opérations que l'on peut effectuer sur une Map.

HashMap

Java propose plusieurs implémentations de Map. HashMap est l'une des plus courantes.

// Make an instance
Map<String, Integer> fruitPrices = new HashMap<>();
Note

Lorsque tu définis une variable Map, il est recommandé de lui donner le type Map plutôt que le type spécifique, comme dans l'exemple ci-dessus. Cette pratique facilite le changement d'implémentation de la Map par la suite.

HashMap possède aussi un constructeur de copie.

// Make a copy of a map
Map<String, Integer> copy = new HashMap<>(fruitPrices);

Ajoute des entrées à la Map avec put.

fruitPrices.put("apple", 100);
fruitPrices.put("pear", 80);
// => { "apple" => 100, "pear" => 80 }

Une seule valeur peut être associée à chaque clé. Appeler put avec la même clé met à jour la valeur de cette clé.

fruitPrices.put("pear", 40);
// => { "apple" => 100, "pear" => 40 }

Utilise get pour obtenir la valeur associée à une clé.

fruitPrices.get("apple"); // => 100

Utilise containsKey pour savoir si la Map contient une clé donnée.

fruitPrices.containsKey("apple");   // => true
fruitPrices.containsKey("orange");  // => false

Supprime des entrées avec remove.

fruitPrices.put("plum", 90);  // Add plum to map
fruitPrices.remove("plum");   // Removes plum from map

La méthode size renvoie le nombre d'entrées.

fruitPrices.size();  // Returns 2

Tu peux utiliser les méthodes keySet ou values pour obtenir les clés ou les valeurs d'une Map sous la forme d'un Set ou d'une collection, respectivement.

fruitPrices.keySet();  // Returns "apple" and "pear" in a set
fruitPrices.values();  // Returns 100 and 80, in a Collection

HashMap utilise hashCode et equals

Les HashMap utilisent les méthodes hashCode et equals d'un objet pour déterminer où stocker les valeurs associées à une clé et comment les récupérer. Pour cette raison, il est important que leurs valeurs de retour ne changent pas entre le stockage et la récupération, sinon la HashMap risque de ne pas retrouver la valeur.

Par exemple, imaginons que l'on ait la classe suivante, destinée à servir de clé dans une Map :

public class Stock {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (Objects.equals(Stock.class, obj.getClass()) && obj instanceof Stock other) {
            return Objects.equals(name, other.name);
        }
        return false;
    }
}

Les méthodes hashCode et equals dépendent du champ name, qui peut être modifié via setName. Modifier le hashCode peut donner des résultats surprenants :

Stock stock = new Stock();
stock.setName("Beanies");

Map<Stock, Integer> stockCount = new HashMap<>();
stockCount.put(stock, 80);

stockCount.get(stock); // Returns 80

Stock other = new Stock();
other.setName("Beanies");

stockCount.get(other); // Returns 80 because "other" and "stock" are equal

stock.setName("Choccies");
stockCount.get(stock); // Returns null because hashCode value has changed

stockCount.get(other);  // Also returns null because "other" and "stock" are not equal

stock.setName("Beanies");
stockCount.get(stock); // HashCode restored, so returns 80 again

stockCount.get(other); // Also returns 80 again because "other" and "stock" are back to equal

Map.of et Map.copyOf

Une autre façon courante de créer des maps consiste à utiliser Map.of ou Map.ofEntries.

// Using Map.of
Map<String, Integer> temperatures = Map.of("Mon", 30, "Tue", 28, "Wed", 32);

// or using Map.ofEntries
Map<String, Integer> temperatures2 = Map.ofEntries(
    Map.entry("Mon", 30),
    Map.entry("Tue", 28),
    Map.entry("Wed", 32)
);

Contrairement à HashMap, elles sont remplies dès le départ et deviennent en lecture seule une fois créées. Map.copyOf crée une copie en lecture seule d'une Map.

Map<String, Integer> readOnlyFruitPrices = Map.copyOf(fruitPrices);

Appeler des méthodes comme put, remove ou clear lève une UnsupportedOperationException.

Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet

Apprends Maps

L'entraînement est verrouillé

Déverrouille 1 exercice de plus pour t'entraîner sur Maps