Как поменять местами ключи и значения в Map
Короткий ответ
Пройдите по парам и соберите новую Map, где ключ и значение поменялись местами:
void main() {
Map<String, Integer> codes = Map.of("DE", 49, "FR", 33, "IT", 39);
Map<Integer, String> byNumber = codes.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey, (a, b) -> a, TreeMap::new));
IO.println(byNumber);
}Результат:
{33=FR, 39=IT, 49=DE}Повторяющиеся значения
Если одно значение встречается у нескольких ключей, соберите ключи в список через groupingBy():
void main() {
var cities = new TreeMap<>(Map.of("Berlin", "DE", "Munich", "DE", "Paris", "FR"));
Map<String, List<String>> byCountry = cities.entrySet().stream()
.collect(Collectors.groupingBy(Map.Entry::getValue, TreeMap::new,
Collectors.mapping(Map.Entry::getKey, Collectors.toList())));
IO.println(byCountry);
}Результат:
{DE=[Berlin, Munich], FR=[Paris]}Циклом
Тот же разворот без потоков:
void main() {
var colors = new LinkedHashMap<String, String>();
colors.put("red", "#f00");
colors.put("green", "#0f0");
var byHex = new LinkedHashMap<String, String>();
colors.forEach((name, hex) -> byHex.put(hex, name));
IO.println(byHex);
}Результат:
{#f00=red, #0f0=green}Частая ошибка
Использовать toMap() без функции слияния, когда значения повторяются. Два одинаковых ключа вызывают исключение:
void main() {
var cities = new TreeMap<>(Map.of("Berlin", "DE", "Munich", "DE"));
var inverted = cities.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
}Результат:
Exception in thread "main" java.lang.IllegalStateException: Duplicate key DE (attempted merging values Berlin and Munich)Передайте третьим аргументом правило слияния, например (a, b) -> a + ", " + b, или используйте groupingBy().
Функции из этого ответа
- Collectors.toMap() — Сборщик, который строит словарь из элементов потока.
- Collectors.groupingBy() — Сборщик, который раскладывает элементы по группам с общим ключом.
- Map.entrySet() — Возвращает все пары «ключ — значение» для обхода.