← Назад к вопросам

Для чего нужна коллекция Map?

1.3 Junior🔥 221 комментариев
#Коллекции

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Коллекция Map

Определение

Map — это интерфейс в Java Collections Framework, который представляет структуру данных для хранения пар ключ-значение (key-value pairs). Map функционирует как словарь или ассоциативный массив, где каждому уникальному ключу соответствует одно значение.

Основное назначение

1. Хранение и получение данных по ключу

Map предоставляет быстрый доступ к значениям по ключу:

Map<String, Integer> ageMap = new HashMap<>();

// Добавление пары ключ-значение
ageMap.put("Alice", 30);
ageMap.put("Bob", 25);
ageMap.put("Charlie", 35);

// Получение значения по ключу O(1) в среднем
Integer aliceAge = ageMap.get("Alice");  // 30

// Проверка наличия ключа
if (ageMap.containsKey("Bob")) {
    System.out.println("Bob найден");
}

2. Основные операции Map

Map<String, String> map = new HashMap<>();

// PUT — добавление/обновление
map.put("key1", "value1");
map.putIfAbsent("key2", "value2");  // Только если ключа нет

// GET — получение значения
String value = map.get("key1");      // "value1"
String def = map.getOrDefault("key3", "default");  // "default"

// REMOVE — удаление
map.remove("key1");
map.remove("key2", "wrongValue");  // Удалит только если значение совпадает

// CHECK — проверка
boolean hasKey = map.containsKey("key1");      // false
boolean hasValue = map.containsValue("value1"); // false

// SIZE — размер
int size = map.size();                          // 0

// CLEAR — очистка
map.clear();

3. Основные реализации Map

HashMap — стандартная, неупорядоченная:

Map<Integer, String> map = new HashMap<>();
map.put(3, "three");
map.put(1, "one");
map.put(2, "two");

for (Integer key : map.keySet()) {
    System.out.println(key);  // 1, 2, 3 или 3, 1, 2 (не гарантирован порядок)
}

LinkedHashMap — сохраняет порядок вставки:

Map<Integer, String> map = new LinkedHashMap<>();
map.put(3, "three");
map.put(1, "one");
map.put(2, "two");

for (Integer key : map.keySet()) {
    System.out.println(key);  // 3, 1, 2 (в порядке вставки)
}

TreeMap — отсортирована по ключам:

Map<Integer, String> map = new TreeMap<>();
map.put(3, "three");
map.put(1, "one");
map.put(2, "two");

for (Integer key : map.keySet()) {
    System.out.println(key);  // 1, 2, 3 (в отсортированном порядке)
}

ConcurrentHashMap — потокобезопасная:

Map<String, Integer> map = new ConcurrentHashMap<>();
map.put("count", 0);

// Безопасна для многопоточного доступа
map.computeIfPresent("count", (k, v) -> v + 1);

4. Итерация по Map

Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 95);
scores.put("Bob", 87);

// Способ 1: По ключам
for (String name : scores.keySet()) {
    System.out.println(name + ": " + scores.get(name));
}

// Способ 2: По значениям
for (Integer score : scores.values()) {
    System.out.println("Score: " + score);
}

// Способ 3: По парам (рекомендуемый)
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
    System.out.println(entry.getKey() + " = " + entry.getValue());
}

// Способ 4: Iterator
Iterator<Map.Entry<String, Integer>> it = scores.entrySet().iterator();
while (it.hasNext()) {
    Map.Entry<String, Integer> entry = it.next();
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

// Способ 5: forEach (Java 8+)
scores.forEach((name, score) -> 
    System.out.println(name + ": " + score)
);

5. Практические примеры использования

Кэширование результатов:

public class Fibonacci {
    private Map<Integer, Long> cache = new HashMap<>();
    
    public long fib(int n) {
        if (cache.containsKey(n)) {
            return cache.get(n);  // Быстрое получение из кэша
        }
        
        long result = (n <= 1) ? n : fib(n - 1) + fib(n - 2);
        cache.put(n, result);
        return result;
    }
}

Счётчик слов:

public class WordCounter {
    public static void main(String[] args) {
        String text = "hello world hello java java java";
        String[] words = text.split(" ");
        
        Map<String, Integer> wordCount = new HashMap<>();
        
        for (String word : words) {
            wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);
        }
        
        // Результат: {hello=2, world=1, java=3}
        wordCount.forEach((word, count) -> 
            System.out.println(word + ": " + count)
        );
    }
}

Конфигурация приложения:

public class Config {
    private static final Map<String, String> properties = new HashMap<>();
    
    static {
        properties.put("app.name", "MyApplication");
        properties.put("app.version", "1.0.0");
        properties.put("database.url", "jdbc:mysql://localhost:3306/mydb");
        properties.put("database.user", "root");
    }
    
    public static String get(String key) {
        return properties.get(key);
    }
    
    public static String get(String key, String defaultValue) {
        return properties.getOrDefault(key, defaultValue);
    }
}

// Использование
String appName = Config.get("app.name");  // "MyApplication"
String port = Config.get("app.port", "8080");  // "8080"

Группировка данных:

public class StudentGrouping {
    static class Student {
        String name;
        String department;
        Student(String name, String department) {
            this.name = name;
            this.department = department;
        }
    }
    
    public static void main(String[] args) {
        List<Student> students = Arrays.asList(
            new Student("Alice", "CS"),
            new Student("Bob", "Math"),
            new Student("Charlie", "CS"),
            new Student("Diana", "Math")
        );
        
        // Группировка по отделению
        Map<String, List<String>> byDepartment = new HashMap<>();
        for (Student student : students) {
            byDepartment.computeIfAbsent(student.department, k -> new ArrayList<>())
                        .add(student.name);
        }
        
        // {CS=[Alice, Charlie], Math=[Bob, Diana]}
        byDepartment.forEach((dept, names) -> 
            System.out.println(dept + ": " + names)
        );
    }
}

6. Производительность основных операций

ОперацияHashMapLinkedHashMapTreeMapConcurrentHashMap
get()O(1)O(1)O(log n)O(1)
put()O(1)O(1)O(log n)O(1)
remove()O(1)O(1)O(log n)O(1)
ПорядокНетВставкиСортированНет
ПотокобезопасностьНетНетНетДа

7. computeIfPresent и computeIfAbsent

Map<String, Integer> map = new HashMap<>();

// computeIfAbsent — вычислить если ключа нет
map.computeIfAbsent("a", k -> 1);  // map.put("a", 1)

// computeIfPresent — вычислить если ключ есть
map.computeIfPresent("a", (k, v) -> v + 1);  // map.put("a", 2)

// compute — вычислить в любом случае
map.compute("a", (k, v) -> v == null ? 1 : v + 1);

// merge — слияние значений
map.merge("a", 10, Integer::sum);  // a = 2 + 10 = 12

Выводы

Map — фундаментальная коллекция Java для:

  • Быстрого поиска значений по ключу (O(1) для HashMap)
  • Хранения пар ключ-значение
  • Кэширования и индексирования данных
  • Подсчёта частот элементов
  • Группировки и классификации данных
  • Конфигурации приложений

Выбор реализации (HashMap, LinkedHashMap, TreeMap) зависит от требований к порядку, производительности и потокобезопасности.

Для чего нужна коллекция Map? | PrepBro