Modding d'Hytale
Bases de Java

11 - HashMap et stockage clé-valeur

Apprenez à stocker et récupérer des données en utilisant les paires clés-valeurs.

Une HashMap stocke des données en paires clés-valeurs, comme un vrai dictionnaire. Vous cherchez un mot (clé) pour trouver sa définition (valeur). C'est parfait pour les données du joueur, les propriétés d'objets, et les paramètres de configuration.

Bases des HashMap

import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        // Crée une HashMap (clés String, valeur Entiers)
        HashMap<String, Integer> playerLevels = new HashMap<>();
        
        // Ajouter une paire clé-valeur
        playerLevels.put("Alice", 10);
        playerLevels.put("Bob", 15);
        playerLevels.put("Charlie", 8);
        
        // Récupérer une valeur par clé
        int aliceLevel = playerLevels.get("Alice");  // 10
        
        System.out.println("Alice is level " + aliceLevel);
    }
}
HashMap vs ArrayList
HashMapArrayList
Non ordonnéOrdonné par index (0, 1, 2, ...)
Accès par clé (peut être de n'importe quel type)Accès par position
Bien pour la recherche de valeursBien pour une liste d'objets
Chaque clé est uniquePeut avoir des doublons
// ArrayList - accès par nombre
ArrayList<String> players = new ArrayList<>();
players.add("Alice");
String player = players.get(0);  // Récupère le premier joueur

// HashMap - accès par nom
HashMap<String, Integer> levels = new HashMap<>();
levels.put("Alice", 10);
int level = levels.get("Alice");  // Récupère le niveau d'Alice

Méthodes courantes sur les HashMaps

Ajouter et Modifier

HashMap<String, Integer> scores = new HashMap<>();

scores.put("Alice", 100);     // Ajoute une nouvelle entrée
scores.put("Bob", 150);
scores.put("Alice", 200);     // Modifie l'entrée existante (Alice à maintenant 200)

Récupérer des valeurs

HashMap<String, Integer> scores = new HashMap<>();
scores.put("Alice", 100);

int score = scores.get("Alice");        // 100
Integer missing = scores.get("Dave");   // null (n'existe pas)

// Récupérer avec valeur par défaut
int score2 = scores.getOrDefault("Dave", 0);  // 0 (Dave n'existe pas, retourne la valeur par défaut)

Vérifier les clés/valeurs

HashMap<String, Integer> scores = new HashMap<>();
scores.put("Alice", 100);

boolean hasAlice = scores.containsKey("Alice");    // true
boolean hasDave = scores.containsKey("Dave");      // false

boolean has100 = scores.containsValue(100);        // true
boolean has200 = scores.containsValue(200);        // false

Supprimer des entrées

HashMap<String, Integer> scores = new HashMap<>();
scores.put("Alice", 100);
scores.put("Bob", 150);

scores.remove("Alice");           // Retire par clé
System.out.println(scores);       // { Bob=150 }

scores.clear();                   // Retire tout
System.out.println(scores);       // {}

Vérification de la taille et du remplissage

HashMap<String, Integer> scores = new HashMap<>();
scores.put("Alice", 100);

int size = scores.size();         // 1
boolean empty = scores.isEmpty(); // false

Boucler sur une HashMap

Boucler sur les clés

HashMap<String, Integer> scores = new HashMap<>();
scores.put("Alice", 100);
scores.put("Bob", 150);
scores.put("Charlie", 75);

for (String name : scores.keySet()) {
    System.out.println(name);
}
// Sortie : Alice, Bob, Charlie (l'ordre peut changer)

Boucler sur les valeurs

for (Integer score : scores.values()) {
    System.out.println(score);
}
// Sortie : 100, 150, 75 (l'ordre peut changer)

Boucler sur les clés et les valeurs

for (String name : scores.keySet()) {
    int score = scores.get(name);
    System.out.println(name + " : " + score);
}

// Ou en utilisant l'entrySet (plus efficace)
for (var entry : scores.entrySet()) {
    String name = entry.getKey();
    int score = entry.getValue();
    System.out.println(name + " : " + score);
}
Ordre dans les HashMaps

Les HashMaps ne maintiennent pas l'ordre d'insertion ! Si vous avez besoin d'ordre, utilisez les LinkedHashMap

import java.util.LinkedHashMap;

LinkedHashMap<String, Integer> orderedScores = new LinkedHashMap<>();
orderedScores.put("Alice", 100);
orderedScores.put("Bob", 150);
orderedScores.put("Charlie", 75);

// Affichera dans l'ordre d'insertion
for (String name : orderedScores.keySet()) {
    System.out.println(name);
}
// Output: Alice, Bob, Charlie (ordre garanti)

Exemples pratiques

Système de statistiques du joueur

import java.util.HashMap;

public class PlayerStats {
    private HashMap<String, Integer> stats;
    
    public PlayerStats() {
        this.stats = new HashMap<>();
        // Initialize default stats
        stats.put("vie", 100);
        stats.put("mana", 50);
        stats.put("force", 10);
        stats.put("défense", 5);
        stats.put("vitesse", 8);
    }
    
    public int getStat(String statName) {
        return stats.getOrDefault(statName, 0);
    }
    
    public void setStat(String statName, int value) {
        stats.put(statName, value);
    }
    
    public void modifyStat(String statName, int amount) {
        int current = getStat(statName);
        stats.put(statName, current + amount);
    }
    
    public void displayStats() {
        System.out.println("=== Statistiques du Joueur ===");
        for (var entry : stats.entrySet()) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
    }
}

// Utilisation
public class Main {
    public static void main(String[] args) {
        PlayerStats stats = new PlayerStats();
        stats.displayStats();
        
        stats.modifyStat("force", 5);
        stats.modifyStat("vie", -20);
        
        System.out.println("\nAprès modifications :");
        stats.displayStats();
    }
}

Base de données de propriétés d'objets

import java.util.HashMap;

public class ItemDatabase {
    private HashMap<String, HashMap<String, Object>> items;
    
    public ItemDatabase() {
        this.items = new HashMap<>();
    }
    
    public void addItem(String itemName) {
        HashMap<String, Object> properties = new HashMap<>();
        properties.put("dégâts", 0);
        properties.put("durabilité", 100);
        properties.put("rareté", "Commun");
        properties.put("stackable", true);
        
        items.put(itemName, properties);
    }
    
    public void setProperty(String itemName, String property, Object value) {
        if (items.containsKey(itemName)) {
            items.get(itemName).put(property, value);
        }
    }
    
    public Object getProperty(String itemName, String property) {
        if (items.containsKey(itemName)) {
            return items.get(itemName).get(property);
        }
        return null;
    }
    
    public void displayItem(String itemName) {
        if (!items.containsKey(itemName)) {
            System.out.println("Objet non trouvé !");
            return;
        }
        
        System.out.println("=== " + itemName + " ===");
        HashMap<String, Object> props = items.get(itemName);
        for (var entry : props.entrySet()) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
    }
}

// Utilisation
public class Main {
    public static void main(String[] args) {
        ItemDatabase db = new ItemDatabase();
        
        db.addItem("Épée en fer");
        db.setProperty("Épée en fer", "dégâts", 15);
        db.setProperty("Épée en fer", "rareté", "Rare");
        
        db.displayItem("Épée en fer");
    }
}

Gestionnaire de configuration

import java.util.HashMap;

public class GameConfig {
    private HashMap<String, String> settings;
    
    public GameConfig() {
        this.settings = new HashMap<>();
        loadDefaults();
    }
    
    private void loadDefaults() {
        settings.put("difficulté", "normale");
        settings.put("volumeMusique", "50");
        settings.put("volumeEffets", "50");
        settings.put("distanceRendu", "10");
        settings.put("afficherFPS", "false");
    }
    
    public String getSetting(String key) {
        return settings.getOrDefault(key, "");
    }
    
    public void setSetting(String key, String value) {
        settings.put(key, value);
        System.out.println("Définit " + key + " à " + value);
    }
    
    public int getIntSetting(String key) {
        String value = getSetting(key);
        try {
            return Integer.parseInt(value);
        } catch (NumberFormatException e) {
            return 0;
        }
    }
    
    public boolean getBooleanSetting(String key) {
        return "true".equalsIgnoreCase(getSetting(key));
    }
    
    public void displaySettings() {
        System.out.println("=== Paramètres du Jeu ===");
        for (var entry : settings.entrySet()) {
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }
    }
}

Inventaire du joueur avec quantités

import java.util.HashMap;

public class Inventory {
    private HashMap<String, Integer> items;
    private int maxSlots;
    
    public Inventory(int maxSlots) {
        this.items = new HashMap<>();
        this.maxSlots = maxSlots;
    }
    
    public boolean addItem(String itemName, int quantity) {
        if (items.size() >= maxSlots && !items.containsKey(itemName)) {
            System.out.println("Inventaire plein !");
            return false;
        }
        
        int current = items.getOrDefault(itemName, 0);
        items.put(itemName, current + quantity);
        System.out.println("Ajouté " + quantity + "x " + itemName);
        return true;
    }
    
    public boolean removeItem(String itemName, int quantity) {
        if (!items.containsKey(itemName)) {
            System.out.println("Nous n'avons pas cet objet !");
            return false;
        }
        
        int current = items.get(itemName);
        if (current < quantity) {
            System.out.println("Pas assez de " + itemName);
            return false;
        }
        
        if (current == quantity) {
            items.remove(itemName);
        } else {
            items.put(itemName, current - quantity);
        }
        
        System.out.println("Retiré " + quantity + "x " + itemName);
        return true;
    }
    
    public int getQuantity(String itemName) {
        return items.getOrDefault(itemName, 0);
    }
    
    public boolean hasItem(String itemName) {
        return items.containsKey(itemName);
    }
    
    public void displayInventory() {
        System.out.println("\n=== Inventaire (" + items.size() + "/" + maxSlots + " emplacements) ===");
        if (items.isEmpty()) {
            System.out.println("Vide");
        } else {
            for (var entry : items.entrySet()) {
                System.out.println(entry.getKey() + " x" + entry.getValue());
            }
        }
    }
}

// Utilisation
public class Main {
    public static void main(String[] args) {
        Inventory inv = new Inventory(10);
        
        inv.addItem("Bois", 64);
        inv.addItem("Pierre", 32);
        inv.addItem("Bois", 20);  // Ajoute à l'existant
        
        inv.displayInventory();
        
        inv.removeItem("Bois", 50);
        inv.displayInventory();
    }
}

Gestionnaire de cooldown

import java.util.HashMap;

public class CooldownManager {
    private HashMap<String, Long> cooldowns;
    
    public CooldownManager() {
        this.cooldowns = new HashMap<>();
    }
    
    public void startCooldown(String ability, long durationMs) {
        long endTime = System.currentTimeMillis() + durationMs;
        cooldowns.put(ability, endTime);
        System.out.println(ability + " est en cooldown pour " + (durationMs / 1000) + " secondes");
    }
    
    public boolean isOnCooldown(String ability) {
        if (!cooldowns.containsKey(ability)) {
            return false;
        }
        
        long endTime = cooldowns.get(ability);
        long now = System.currentTimeMillis();
        
        if (now >= endTime) {
            cooldowns.remove(ability);
            return false;
        }
        
        return true;
    }
    
    public long getRemainingTime(String ability) {
        if (!isOnCooldown(ability)) {
            return 0;
        }
        
        long endTime = cooldowns.get(ability);
        long now = System.currentTimeMillis();
        return (endTime - now) / 1000;  // Retourne les secondes
    }
    
    public boolean useAbility(String ability, long cooldownSeconds) {
        if (isOnCooldown(ability)) {
            long remaining = getRemainingTime(ability);
            System.out.println(ability + " est en cooldown (" + remaining + "s restantes)");
            return false;
        }
        
        System.out.println("Utilisation de " + ability + " !");
        startCooldown(ability, cooldownSeconds * 1000);
        return true;
    }
}

HashMap avec des objets personnalisés

Vous pouvez stocker vos propres classes en valeurs :

public class Player {
    private String name;
    private int level;
    private int health;
    
    public Player(String name, int level) {
        this.name = name;
        this.level = level;
        this.health = 100;
    }
    
    // Getters et Setters...
    
    @Override
    public String toString() {
        return name + " (Niv. " + level + ", Vie : " + health + ")";
    }
}

public class Main {
    public static void main(String[] args) {
        HashMap<String, Player> players = new HashMap<>();
        
        players.put("player1", new Player("Alice", 10));
        players.put("player2", new Player("Bob", 15));
        
        // Récupérer et utiliser un joueur
        Player alice = players.get("player1");
        System.out.println(alice);
    }
}

HashMaps imbriqués

Les HashMaps peuvent contenir d'autres HashMaps

// Stocker de multiples propriétés par joueur
HashMap<String, HashMap<String, Integer>> playerData = new HashMap<>();

// Ajouter des joueurs avec des statistiques
HashMap<String, Integer> aliceStats = new HashMap<>();
aliceStats.put("niveau", 10);
aliceStats.put("vie", 100);
aliceStats.put("mana", 50);
playerData.put("Alice", aliceStats);

// Accéder aux données imbriquées
int aliceLevel = playerData.get("Alice").get("niveau");
System.out.println("Niveau d'Alice : " + aliceLevel);

Exercices pratiques

  1. Annuaire téléphonique : créez un annuaire téléphonique qui stocke des noms et numéros de téléphone associés. Ajoutez des méthodes pour :

    • Ajouter un contact
    • Trouver un numéro à partir d'un nom
    • Supprimer un contact
    • Afficher tous les contacts
  2. Gestionnaire de notes : stockez les noms des étudiants et leurs notes. Créez des méthodes pour :

    • Ajouter un étudiant avec une note
    • Modifier la note
    • Calculer la moyenne de la classe
    • Trouver la note la plus haute
  3. Compteur de mots : écrivez un programme qui compte combien de fois chaque mot apparait dans une phrase en utilisant une HashMap.

  4. Boutique d'objets : créez une boutique où les objets ont un nom et un prix. Ajoutez des méthodes pour :

    • Ajouter un objet avec son prix
    • Récupérer le prix d'un objet
    • Appliquer une réduction sur tous les objets
    • Afficher tous les objets et leurs prix