Hytale Modding
Conceptos básicos de Java

11 - Almacenamiento de HashMap y clave-valor

Aprende a almacenar y recuperar datos usando pares clave-valor.

Un HashMap almacena datos en pares clave-valor, al igual que un diccionario del mundo real. Buscas una palabra (clave) para encontrar su definición (valor). Esto es perfecto para datos del jugador, propiedades de objetos y configuraciones.

Conceptos básicos del HashMap

import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        // Crea un HashMap (String keys, Integer values)
        HashMap<String, Integer> playerLevels = new HashMap<>();
        
        // agrega pares clave-valor
        playerLevels.put("Alice", 10);
        playerLevels.put("Bob", 15);
        playerLevels.put("Charlie", 8);
        
        // obtener un valor por su clave
        int aliceLevel = playerLevels.get("Alice");  // 10
        
        System.out.println("Alice es nivel " + aliceLevel);
    }
}
HashMap vs ArrayList
HashMapArrayList
Sin ordenarOrdenado por el índice (0, 1, 2...)
Acceso por clave (puede ser de cualquier tipo)Acceso por posición
Útil para buscar valoresÚtil para listas de elementos
Cada clave es únicaPuede tener duplicados
// ArrayList - acceso por número
ArrayList<String> players = new ArrayList<>();
players.add("Alice");
String player = players.get(0);  // Obtener el primer jugador

// HashMap - acceso por nombre
HashMap<String, Integer> levels = new HashMap<>();
levels.put("Alice", 10);
int level = levels.get("Alice");  // Obtener el nivel de Alice

Métodos comunes del HashMap

Agregar y Actualizar

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

scores.put("Alice", 100);     // Añadir una nueva entrada
scores.put("Bob", 150);
scores.put("Alice", 200);     // Actualizar una entrada existente (Alice ahora tendrá 200)

Obtener Valores

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

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

// Obtener con valor predeterminado
int score2 = scores.getOrDefault("Dave", 0);  // 0 (devuelve el valor predeterminado)

Comprobación de Claves/Valores

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

boolean hasAlice = scores.containsKey("Alice");    // Verdadero
boolean hasDave = scores.containsKey("Dave");      // Falso

boolean has100 = scores.containsValue(100);        // Verdadero
boolean has200 = scores.containsValue(200);        // Falso

Eliminación de Entradas

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

scores.remove("Alice");           // Eliminar por entrada
System.out.println(scores);       // {Bob=150}

scores.clear();                   // Eliminar todo
System.out.println(scores);       // {}

Comprobación de Tamaño y Vacío

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

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

Recorriendo un HashMap

Recorrer Claves

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);
}
// Salida: Alice, Bob, Charlie (el orden puede variar)

Recorrer Valores

for (Integer score : scores.values()) {
    System.out.println(score);
}
// Salida: 100, 150, 75 (el orden puede variar)

Recorrer Claves y Valores

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

// O usando un entrySet (más eficiente)
for (var entry : scores.entrySet()) {
    String name = entry.getKey();
    int score = entry.getValue();
    System.out.println(name + ": " + score);
}
Orden del HashMap

¡HashMap no mantiene el orden de inserción! Si necesitas mantener el orden, usa LinkedHashMap:

import java.util.LinkedHashMap;

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

// Se imprimirá en orden de inserción
for (String name : orderedScores.keySet()) {
    System.out.println(name);
}
// Salida: Alice, Bob, Charlie (orden garantizado)

Ejemplos Prácticos

Sistema de Estadísticas del Jugador

import java.util.HashMap;

public class PlayerStats {
    private HashMap<String, Integer> stats;
    
    public PlayerStats() {
        this.stats = new HashMap<>();
        // Inicializar las estadísticas predeterminadas
        stats.put("health", 100);
        stats.put("mana", 50);
        stats.put("strength", 10);
        stats.put("defense", 5);
        stats.put("speed", 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("=== Player Stats ===");
        for (var entry : stats.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}

// Forma de utilizarlo
public class Main {
    public static void main(String[] args) {
        PlayerStats stats = new PlayerStats();
        stats.displayStats();
        
        stats.modifyStat("strength", 5);
        stats.modifyStat("health", -20);
        
        System.out.println("\nAfter modifications:");
        stats.displayStats();
    }
}

Base de Datos de las Propiedades de un Objeto

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("damage", 0);
        properties.put("durability", 100);
        properties.put("rarity", "Common");
        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("Item not found!");
            return;
        }
        
        System.out.println("=== " + itemName + " ===");
        HashMap<String, Object> props = items.get(itemName);
        for (var entry : props.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}

// Forma de utilizarlo
public class Main {
    public static void main(String[] args) {
        ItemDatabase db = new ItemDatabase();
        
        db.addItem("Iron Sword");
        db.setProperty("Iron Sword", "damage", 15);
        db.setProperty("Iron Sword", "rarity", "Uncommon");
        
        db.displayItem("Iron Sword");
    }
}

Gestor de Configuración

import java.util.HashMap;

public class GameConfig {
    private HashMap<String, String> settings;
    
    public GameConfig() {
        this.settings = new HashMap<>();
        loadDefaults();
    }
    
    private void loadDefaults() {
        settings.put("difficulty", "normal");
        settings.put("musicVolume", "50");
        settings.put("sfxVolume", "50");
        settings.put("renderDistance", "10");
        settings.put("showFPS", "false");
    }
    
    public String getSetting(String key) {
        return settings.getOrDefault(key, "");
    }
    
    public void setSetting(String key, String value) {
        settings.put(key, value);
        System.out.println("Set " + key + " to " + 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("=== Game Settings ===");
        for (var entry : settings.entrySet()) {
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }
    }
}

Inventario del Jugador con Cantidades

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("Inventory full!");
            return false;
        }
        
        int current = items.getOrDefault(itemName, 0);
        items.put(itemName, current + quantity);
        System.out.println("Added " + quantity + "x " + itemName);
        return true;
    }
    
    public boolean removeItem(String itemName, int quantity) {
        if (!items.containsKey(itemName)) {
            System.out.println("Don't have that item!");
            return false;
        }
        
        int current = items.get(itemName);
        if (current < quantity) {
            System.out.println("Not enough " + itemName);
            return false;
        }
        
        if (current == quantity) {
            items.remove(itemName);
        } else {
            items.put(itemName, current - quantity);
        }
        
        System.out.println("Removed " + 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=== Inventory (" + items.size() + "/" + maxSlots + " slots) ===");
        if (items.isEmpty()) {
            System.out.println("Empty");
        } else {
            for (var entry : items.entrySet()) {
                System.out.println(entry.getKey() + " x" + entry.getValue());
            }
        }
    }
}

// Forma de utilizarlo
public class Main {
    public static void main(String[] args) {
        Inventory inv = new Inventory(10);
        
        inv.addItem("Wood", 64);
        inv.addItem("Stone", 32);
        inv.addItem("Wood", 20);  // Se suma a la cantidad ya existente
        
        inv.displayInventory();
        
        inv.removeItem("Wood", 50);
        inv.displayInventory();
    }
}

Gestor del Tiempo de Reutilización

HashMap con Objetos Personalizados

Almacena tus propias clases como un valor:

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 and setters...
    
    @Override
    public String toString() {
        return name + " (Lv. " + level + ", HP: " + 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));
        
        // Obtener y usar un jugador
        Player alice = players.get("player1");
        System.out.println(alice);
    }
}

HashMaps anidados

Los HashMaps pueden contener otros HashMaps:

// Almacenar múltiples propiedades por jugador
HashMap<String, HashMap<String, Integer>> playerData = new HashMap<>();

// Agregar jugador con estadísticas
HashMap<String, Integer> aliceStats = new HashMap<>();
aliceStats.put("level", 10);
aliceStats.put("health", 100);
aliceStats.put("mana", 50);
playerData.put("Alice", aliceStats);

// Acceder a datos anidados
int aliceLevel = playerData.get("Alice").get("level");
System.out.println("Nivel de Alice: " + aliceLevel);

Ejercicios Prácticos

  1. Agenda telefónica: Crea una agenda telefónica que almacena nombres y números de teléfono. Añadir métodos a:

    • Añadir contacto
    • Encontrar un número por el nombre
    • Borrar contacto
    • Mostrar todos los contactos
  2. Gestor de calificaciones: Almacena los nombres de los estudiantes y sus calificaciones. Añadir métodos a:

    • Añadir un estudiante con su calificación
    • Actualizar calificación
    • Calcular la media de la clase
    • Encontrar la calificación más alta
  3. Cuentapalabras: Escribe un programa que cuenta las veces que aparece cada palabra en una frase haciendo uso de un HashMap.

  4. Tienda de objetos: Crea una tienda donde los objetos tengan nombre y precio. Añadir métodos a:

    • Añadir un objeto con precio
    • Obtener el precio del objeto
    • Aplicar un descuento a todos los objetos
    • Mostrar todos los objetos y precios