Автор оригинала: Ekaterina Galkina.
1. Обзор
Преобразование List в Map – обычная задача. В этом уроке мы рассмотрим несколько способов сделать это.
Предположим, что каждый элемент List имеет идентификатор, который будет использоваться в качестве ключа в результирующей Карте .
Дальнейшее чтение:
Преобразование списка в Карту С помощью Пользовательского поставщика
Преобразование списка в строку в Java
Преобразование между списком и набором в Java
2. Пример Структуры Данных
Сначала мы смоделируем элемент:
public class Animal { private int id; private String name; // constructor/getters/setters }
Поле id уникально, поэтому мы можем сделать его ключом.
Давайте начнем преобразование традиционным способом.
3. Перед Java 8
Очевидно, что мы можем преобразовать List в Map с помощью основных методов Java:
public MapconvertListBeforeJava8(List list) { Map map = new HashMap<>(); for (Animal animal : list) { map.put(animal.getId(), animal); } return map; }
Теперь мы тестируем преобразование:
@Test public void whenConvertBeforeJava8_thenReturnMapWithTheSameElements() { Mapmap = convertListService .convertListBeforeJava8(list); assertThat( map.values(), containsInAnyOrder(list.toArray())); }
4. С Java 8
Начиная с Java 8, мы можем преобразовать Список в Карту с помощью потоков и Коллекторов :
public MapconvertListAfterJava8(List list) { Map map = list.stream() .collect(Collectors.toMap(Animal::getId, animal -> animal)); return map; }
Опять же, давайте убедимся, что преобразование сделано правильно:
@Test public void whenConvertAfterJava8_thenReturnMapWithTheSameElements() { Mapmap = convertListService.convertListAfterJava8(list); assertThat( map.values(), containsInAnyOrder(list.toArray())); }
5. Использование библиотеки Guava
Помимо основной Java, мы можем использовать сторонние библиотеки для преобразования.
5.1. Конфигурация Maven
Во-первых, нам нужно добавить следующую зависимость к вашему pom.xml :
com.google.guava guava 23.6.1-jre
Последнюю версию этой библиотеки всегда можно найти здесь .
5.2. Конвертация С Помощью Maps.uniqueIndex()
Во-вторых, давайте используем метод Maps.uniqueIndex() для преобразования Списка в Карту :
public MapconvertListWithGuava(List list) { Map map = Maps .uniqueIndex(list, Animal::getId); return map; }
Наконец, мы тестируем преобразование:
@Test public void whenConvertWithGuava_thenReturnMapWithTheSameElements() { Mapmap = convertListService .convertListWithGuava(list); assertThat( map.values(), containsInAnyOrder(list.toArray())); }
6. Использование библиотеки Apache Commons
Мы также можем сделать преобразование с помощью метода библиотеки Apache Commons.
6.1. Конфигурация Maven
Во-первых, давайте включим зависимость Maven:
org.apache.commons commons-collections4 4.2
Последняя версия этой зависимости доступна здесь .
6.2. MapUtils
Во-вторых, мы сделаем преобразование с помощью MapUtils.populateMap() :
public MapconvertListWithApacheCommons2(List list) { Map map = new HashMap<>(); MapUtils.populateMap(map, list, Animal::getId); return map; }
Наконец, мы можем убедиться, что он работает так, как ожидалось:
@Test public void whenConvertWithApacheCommons2_thenReturnMapWithTheSameElements() { Mapmap = convertListService .convertListWithApacheCommons2(list); assertThat( map.values(), containsInAnyOrder(list.toArray())); }
7. Конфликт ценностей
Давайте проверим, что произойдет, если поле id не является уникальным.
7.1. Список животных С Дублированными Идентификаторами
Во-первых, мы создаем List of Animal s с неуникальным id s:
@Before public void init() { this.duplicatedIdList = new ArrayList<>(); Animal cat = new Animal(1, "Cat"); duplicatedIdList.add(cat); Animal dog = new Animal(2, "Dog"); duplicatedIdList.add(dog); Animal pig = new Animal(3, "Pig"); duplicatedIdList.add(pig); Animal cow = new Animal(4, "Cow"); duplicatedIdList.add(cow); Animal goat= new Animal(4, "Goat"); duplicatedIdList.add(goat); }
Как показано выше, корова и коза имеют один и тот же идентификатор .
7.2. Проверка поведения
Ява Карта ‘s класть() метод реализован таким образом, что последнее добавленное значение перезаписывает предыдущее с тем же ключом.
По этой причине традиционное преобразование и Apache Commons MapUtils.populateMap() ведут себя одинаково:
@Test public void whenConvertBeforeJava8_thenReturnMapWithRewrittenElement() { Mapmap = convertListService .convertListBeforeJava8(duplicatedIdList); assertThat(map.values(), hasSize(4)); assertThat(map.values(), hasItem(duplicatedIdList.get(4))); } @Test public void whenConvertWithApacheCommons_thenReturnMapWithRewrittenElement() { Map map = convertListService .convertListWithApacheCommons(duplicatedIdList); assertThat(map.values(), hasSize(4)); assertThat(map.values(), hasItem(duplicatedIdList.get(4))); }
Мы видим, что козел перезаписывает корову с тем же идентификатором .
Однако Collectors.toMap() и MapUtils.populateMap() throw IllegalStateException и IllegalArgumentException соответственно :
@Test(expected = IllegalStateException.class) public void givenADupIdList_whenConvertAfterJava8_thenException() { convertListService.convertListAfterJava8(duplicatedIdList); } @Test(expected = IllegalArgumentException.class) public void givenADupIdList_whenConvertWithGuava_thenException() { convertListService.convertListWithGuava(duplicatedIdList); }
8. Заключение
В этой краткой статье мы рассмотрели различные способы преобразования List в Map, приведя примеры с ядром Java, а также некоторые популярные сторонние библиотеки.
Как обычно, полный исходный код доступен на GitHub .