Lista Java 8 en Mapa

Quiero traducir una Lista de objetos en un Mapa utilizando las secuencias y lambdas de Java 8.

Así es como lo escribiría en Java 7 y abajo.

private Map nameMap(List choices) { final Map hashMap = new HashMap(); for (final Choice choice : choices) { hashMap.put(choice.getName(), choice); } return hashMap; } 

Puedo lograr esto fácilmente usando Java 8 y Guava, pero me gustaría saber cómo hacerlo sin Guava.

En Guava:

 private Map nameMap(List choices) { return Maps.uniqueIndex(choices, new Function() { @Override public String apply(final Choice input) { return input.getName(); } }); } 

Y guayaba con Java 8 lambdas.

 private Map nameMap(List choices) { return Maps.uniqueIndex(choices, Choice::getName); } 

Según la documentación de los Collectors , es tan simple como:

 Map result = choices.stream().collect(Collectors.toMap(Choice::getName, Function.identity())); 

Si no se garantiza que su clave sea única para todos los elementos de la lista, debe convertirla en un Map> Map lugar de un Map

 Map> result = choices.stream().collect(Collectors.groupingBy(Choice::getName)); 

Use getName () como la clave y la opción como el valor del mapa:

 Map result = choices.stream().collect(Collectors.toMap(Choice::getName, c -> c)); 

Aquí hay otro en caso de que no quiera usar Collectors.toMap ()

 Map result = choices.stream().collect(HashMap::new, (m, c) -> m.put(c.getName(), c), (m, u) -> {}); 

Una opción más de manera simple

 Map map = new HashMap<>(); choices.forEach(e->map.put(e.getName(),e)); 

Si no te importa usar una lib de terceros ( Vavr (anteriormente conocida como Javaslang) ) podrías usar nuevas colecciones inmutables poderosas:

 // import javaslang.collection.*; Map map = list.toMap(choice -> Tuple.of(choice.getName(), choice)); 

También hay muchos métodos para convertir colecciones de Java adelante y atrás.

Por favor, lea más sobre las nuevas colecciones aquí.

Descargo de responsabilidad: soy el creador de Vavr.

Si no te importa usar bibliotecas de terceros, el cíclope-reac lib de AOL (la revelación soy colaborador) tiene extensiones para todos los tipos de colecciones JDK , incluidos List y Map .

 ListX choices; Map map = choices.toMap(c-> c.getName(),c->c); 

Intenté hacer esto y descubrí que, utilizando las respuestas anteriores, al usar Functions.identity() para la clave del Mapa, tuve problemas con el uso de un método local como this::localMethodName para que realmente funcionara debido a problemas al escribir .

Functions.identity() realidad hace algo al tipeo en este caso por lo que el método solo funcionaría al devolver Object y aceptar un parámetro de Object

Para resolver esto, terminé abandonando Functions.identity() y usando s->s en s->s lugar.

Entonces mi código, en mi caso para listar todos los directorios dentro de un directorio, y para cada uno usar el nombre del directorio como la clave del mapa y luego llamar a un método con el nombre del directorio y devolver una colección de artículos, se ve así:

 Map> items = Arrays.stream(itemFilesDir.listFiles(File::isDirectory)) .map(File::getName) .collect(Collectors.toMap(s->s, this::retrieveBrandItems)); 

Por ejemplo, si desea convertir campos de objeto para mapear:

Objeto de ejemplo:

 class Item{ private String code; private String name; public Item(String code, String name) { this.code = code; this.name = name; } //getters and setters } 

Y operación convertir lista al mapa:

 List list = new ArrayList<>(); list.add(new Item("code1", "name1")); list.add(new Item("code2", "name2")); Map map = list.stream() .collect(Collectors.toMap(Item::getCode(), Item::getName())); 

Puede crear un flujo de los índices usando un IntStream y luego convertirlos a un mapa:

 Map map = IntStream.range(0,items.size()) .boxed() .collect(Collectors.toMap (i -> i, i -> items.get(i))); 

Yo uso esta syntax

 Map> choiceMap = choices.stream().collect(Collectors.groupingBy(choice -> choice.getName())); 
 Map> collect = Arrays.asList(Locale.getAvailableLocales()).stream().collect(Collectors .toMap(l -> l.getDisplayCountry(), l -> Collections.singleton(l.getDisplayLanguage()))); 

La mayoría de las respuestas enumeradas, pierden un caso cuando la lista tiene elementos duplicados . En ese caso, la respuesta arrojará IllegalStateException . Consulte el siguiente código para manejar los duplicados de la lista también:

 public Map convertListToMap(List choices) { return choices.stream() .collect(Collectors.toMap(Choice::getName, choice -> choice, (oldValue, newValue) -> newValue)); } 

Aquí está la solución de StreamEx

 StreamEx.of(choices).toMap(Choice::getName, c -> c); 

Es posible usar transmisiones para hacer esto. Para eliminar la necesidad de utilizar explícitamente los Collectors , es posible importar a toMap estáticamente (como recomienda Effective Java, tercera edición).

 import static java.util.stream.Collectors.toMap; private static Map nameMap(List choices) { return choices.stream().collect(toMap(Choice::getName, it -> it)); } 

Escribiré cómo convertir una lista en un mapa usando generics e inversión de control . ¡Solo un método universal!

Tal vez tenemos una lista de enteros o una lista de objetos. Entonces la pregunta es la siguiente: ¿cuál debería ser la clave del mapa?

crear interfaz

 public interface KeyFinder { K getKey(E e); } 

ahora usando inversión de control:

  static  Map listToMap(List list, KeyFinder finder) { return list.stream().collect(Collectors.toMap(e -> finder.getKey(e) , e -> e)); } 

Por ejemplo, si tenemos objetos de libro, esta clase es para elegir la clave del mapa

 public class BookKeyFinder implements KeyFinder { @Override public Long getKey(Book e) { return e.getPrice() } } 
 Map map=list.stream().collect(Collectors.toMap(Choice::getName, s->s)); 

Incluso sirve este propósito para mí,

 Map map= list1.stream().collect(()-> new HashMap(), (r,s) -> r.put(s.getString(),s),(r,s) -> r.putAll(s)); 

Esto se puede hacer de 2 maneras. Deje que la persona sea la clase que vamos a usar para demostrarlo.

 public class Person { private String name; private int age; public String getAge() { return age; } } 

Deje que las personas sean la lista de personas que se convertirán al mapa

1.Utilización de foreach simple y una expresión de Lambda en la lista

 Map> mapPersons = new HashMap<>(); persons.forEach(p->mapPersons.put(p.getAge(),p)); 

2. Usar Collectors on Stream definido en la Lista dada.

  Map> mapPersons = persons.stream().collect(Collectors.groupingBy(Person::getAge));