Как преобразовать список в карту в Java

1. Обзор

Преобразование списка в карту - обычная задача. В этом руководстве мы рассмотрим несколько способов сделать это.

Предположим, что каждый элемент списка имеет идентификатор, который будет использоваться в качестве ключа в результирующей карте .

2. Пример структуры данных

Для начала смоделируем элемент:

public class Animal { private int id; private String name; // constructor/getters/setters }

Поле id уникально, поэтому мы можем сделать его ключевым.

Начнем конвертировать традиционным способом.

3. До Java 8

Очевидно, мы можем преобразовать список в карту с помощью основных методов Java:

public Map convertListBeforeJava8(List list) { Map map = new HashMap(); for (Animal animal : list) { map.put(animal.getId(), animal); } return map; }

Проверим преобразование:

@Test public void whenConvertBeforeJava8_thenReturnMapWithTheSameElements() { Map map = convertListService .convertListBeforeJava8(list); assertThat( map.values(), containsInAnyOrder(list.toArray())); }

4. С Java 8

Начиная с Java 8, мы можем преобразовывать список в карту, используя потоки и коллекторы :

 public Map convertListAfterJava8(List list) { Map map = list.stream() .collect(Collectors.toMap(Animal::getId, animal -> animal)); return map; }

Опять же, убедимся, что преобразование выполнено правильно:

@Test public void whenConvertAfterJava8_thenReturnMapWithTheSameElements() { Map map = 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 Map convertListWithGuava(List list) { Map map = Maps .uniqueIndex(list, Animal::getId); return map; }

Наконец, давайте протестируем преобразование:

@Test public void whenConvertWithGuava_thenReturnMapWithTheSameElements() { Map map = 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 Map convertListWithApacheCommons2(List list) { Map map = new HashMap(); MapUtils.populateMap(map, list, Animal::getId); return map; }

Наконец, давайте убедимся, что он работает должным образом:

@Test public void whenConvertWithApacheCommons2_thenReturnMapWithTheSameElements() { Map map = convertListService .convertListWithApacheCommons2(list); assertThat( map.values(), containsInAnyOrder(list.toArray())); }

7. Конфликт ценностей

Давайте проверим, что будет, если поле id не уникально.

7.1. Список из животных с дубликатами Id s

Во - первых, давайте создадим список из животных s с неуникальным идентификатор 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. Проверка поведения

Java Map‘s put() method is implemented so that the latest added value overwrites the previous one with the same key.

For this reason, the traditional conversion and Apache Commons MapUtils.populateMap() behave in the same way:

@Test public void whenConvertBeforeJava8_thenReturnMapWithRewrittenElement() { Map map = 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))); }

As can be seen, the goat overwrites the cow with the same id.

Unlike that, Collectors.toMap() and MapUtils.populateMap() throw IllegalStateException and IllegalArgumentException respectively:

@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. Conclusion

В этой быстрой статье мы рассмотрели различные способы преобразования списка в карту, приведя примеры с использованием ядра Java, а также некоторых популярных сторонних библиотек.

Как обычно, полный исходный код доступен на GitHub.