Come convertire un elenco in una mappa in Java

1. Panoramica

La conversione da elenco a mappa è un'attività comune. In questo tutorial, tratteremo diversi modi per farlo.

Assumeremo che ogni elemento della lista abbia un identificatore che sarà usato come chiave nella mappa risultante .

2. Struttura dei dati di esempio

In primo luogo, modelliamo l'elemento:

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

Il campo id è unico, quindi possiamo renderlo la chiave.

Cominciamo a convertire con il modo tradizionale.

3. Prima di Java 8

Evidentemente, possiamo convertire una lista in una mappa usando i metodi Java di base:

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

Testiamo la conversione:

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

4. Con Java 8

A partire da Java 8 possiamo convertire un elenco in una mappa utilizzando flussi e raccoglitori :

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

Ancora una volta, assicuriamoci che la conversione sia eseguita correttamente:

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

5. Utilizzo della libreria Guava

Oltre a Java core, possiamo utilizzare librerie di terze parti per la conversione.

5.1. Configurazione Maven

Innanzitutto, dobbiamo aggiungere la seguente dipendenza al nostro pom.xml :

 com.google.guava guava 23.6.1-jre 

L'ultima versione di questa libreria è sempre disponibile qui.

5.2. Conversione con Maps.uniqueIndex ()

In secondo luogo, utilizziamo il metodo Maps.uniqueIndex () per convertire un elenco in una mappa :

public Map convertListWithGuava(List list) { Map map = Maps .uniqueIndex(list, Animal::getId); return map; }

Infine, testiamo la conversione:

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

6. Utilizzo della libreria Apache Commons

Possiamo anche fare una conversione con ilmetodo della libreria Apache Commons.

6.1. Configurazione Maven

Innanzitutto, includiamo la dipendenza da Maven:

 org.apache.commons commons-collections4 4.2 

L'ultima versione di questa dipendenza è disponibile qui.

6.2. MapUtils

In secondo luogo, effettueremo la conversione utilizzando MapUtils.populateMap () :

public Map convertListWithApacheCommons2(List list) { Map map = new HashMap(); MapUtils.populateMap(map, list, Animal::getId); return map; }

Infine, assicuriamoci che funzioni come previsto:

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

7. Conflitto di valori

Controlliamo cosa succede se il campo id non è univoco.

7.1. Lista di animali Con duplicato Id s

Innanzitutto, creiamo un elenco di animali con ID non univoci :

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

Come mostrato sopra, la mucca e la capra hanno lo stesso ID .

7.2. Verifica del comportamento

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

In questo rapido articolo, abbiamo coperto vari modi per convertire un elenco in una mappa, fornendo esempi con Java di base e alcune popolari librerie di terze parti.

Come al solito, il codice sorgente completo è disponibile su GitHub.