Рубрики
Без рубрики

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

Узнайте о различных способах преобразования списка в карту на Java, используя основные функциональные возможности и некоторые популярные библиотеки

Автор оригинала: 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 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. Список животных С Дублированными Идентификаторами

Во-первых, мы создаем 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() {

    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)));
}

Мы видим, что козел перезаписывает корову с тем же идентификатором .

Однако 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 .