Почему Map в Java не реализует интерфейс Iterable?

Ответ

Map не реализует Iterable, потому что не существует однозначного ответа на вопрос "что итерировать?". Map содержит три логически различных набора данных: ключи, значения и пары (записи).

Для итерации используются явные методы:

  1. Set<K> keySet() — итерация по ключам.
  2. Collection<V> values() — итерация по значениям.
  3. Set<Map.Entry<K, V>> entrySet() — итерация по парам ключ-значение (наиболее частый случай).

Примеры:

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

// 1. Итерация по записям (рекомендуется)
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
    System.out.printf("%s: %dn", entry.getKey(), entry.getValue());
}

// 2. Итерация по ключам
for (String name : scores.keySet()) {
    System.out.println(name);
}

// 3. Итерация по значениям
for (Integer score : scores.values()) {
    System.out.println(score);
}

// 4. С использованием Stream API
scores.entrySet().stream()
       .filter(entry -> entry.getValue() > 90)
       .forEach(System.out::println);

Если бы Map был Iterable, пришлось бы выбирать один вариант по умолчанию (например, entrySet), что скрывало бы другие возможности и усложняло API. Явные методы дают разработчику полный контроль и ясность.

Ответ 18+ 🔞

Давайте разберёмся с этой, блядь, дилеммой, как с Герасимом и Муму. Почему Map, сука, не Iterable? А потому что это, ёпта, как спросить у немого: «Ну что, Герасим, расскажи, как дела?». А он тебе: «Мууу...». И нихуя не понятно, о чём речь — то ли про ключи, то ли про значения, то ли про всю эту хуйню вместе.

Вот представь: Map — это такой здоровый мужик, у которого в карманах три разных мешка. В одном — ключи (keySet), в другом — значения (values), а в третьем — пары, записи эти, entrySet, где всё вместе лежит, связанное. И если бы Map был Iterable, пришлось бы выбирать: какой, блядь, мешок по умолчанию вытряхивать? Это ж пиздец неоднозначность! Один скажет: «Да итерируй мне ключи!». Другой: «Нахуй ключи, дай значения!». А третий, самый умный: «Мне пары подавай, чтобы ключ и значение разом!». И все будут правы, блядь. Вот чтобы этой драки не было, сделали явные методы — иди, сука, сам решай, что тебе нужно.

Вот тебе примеры, как с этим жить, не сходя с ума:

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

// 1. Итерация по записям (самый частый случай, рекомендую)
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
    System.out.printf("%s: %dn", entry.getKey(), entry.getValue());
}

// 2. Итерация по ключам
for (String name : scores.keySet()) {
    System.out.println(name);
}

// 3. Итерация по значениям
for (Integer score : scores.values()) {
    System.out.println(score);
}

// 4. Ну и на Stream API, для полного счастья
scores.entrySet().stream()
       .filter(entry -> entry.getValue() > 90)
       .forEach(System.out::println);

Видишь? Всё явно, блядь. Никаких «Мууу» неоднозначных. Хочешь ключи — keySet(), хочешь значения — values(), а хочешь всё разом — entrySet(). Чисто, понятно, и в рот меня чих-пых — никто не запутается. Если бы Map был Iterable, пришлось бы гадать, что там итерируется по умолчанию, и это было бы пиздопроебибно. А так — красота, ядрёна вошь! Сам решаешь, что тебе нужно, и не паришься.