Lista Java 8 no mapa

Eu quero traduzir uma lista de objects em um mapa usando os streams e lambdas do Java 8.

É assim que eu escreveria no Java 7 e abaixo.

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

Eu posso fazer isso facilmente usando o Java 8 e o Guava, mas eu gostaria de saber como fazer isso sem o Goiaba.

Em goiaba:

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

E Goiaba com Java 8 lambdas.

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

   

Com base na documentação do Collectors , é tão simples quanto:

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

Se a sua chave NÃO tem garantia de ser única para todos os elementos da lista, você deve convertê-la para um Map> invés de um Map

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

Use getName () como chave e escolha como o valor do mapa:

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

Aqui está outro caso você não queira usar Collectors.toMap ()

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

Mais uma opção de maneira simples

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

Se você não se importa em usar uma biblioteca de terceiros ( Vavr (anteriormente conhecida como Javaslang) ) você pode usar novas e imutáveis ​​collections imutáveis:

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

Existem também muitos methods para converter collections Java para trás e para trás.

Por favor, leia mais sobre as novas collections aqui.

Disclaimer: Eu sou o criador do Vavr.

Se você não se importar em usar bibliotecas de terceiros, a lib -cyclops-react da AOL (disclosure eu sou um colaborador) tem extensões para todos os tipos de coleção do JDK , incluindo List e Map .

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

Eu estava tentando fazer isso e descobri que, usando as respostas acima, quando usando Functions.identity() para a chave para o mapa, então eu tive problemas com o uso de um método local como this::localMethodName para realmente funcionar por causa de problemas de digitação .

Functions.identity() na verdade faz alguma coisa com a digitação nesse caso, então o método só funcionaria retornando Object e aceitando um parâmetro de Object

Para resolver isso, acabei abandonando Functions.identity() e usando s->s .

Então meu código, no meu caso para listar todos os diretórios dentro de um diretório, e para cada um uso o nome do diretório como a chave para o mapa e depois chamar um método com o nome do diretório e retornar uma coleção de itens, se parece com:

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

Por exemplo, se você quiser converter campos de object para mapear:

Exemplo de object:

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

E operação converter lista para o 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())); 

Você pode criar um stream dos índices usando um IntStream e depois convertê-los em um mapa:

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

Eu uso essa 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()))); 

A maioria das respostas listadas, falta um caso em que a lista tem itens duplicados . Nesse caso, a resposta lançará IllegalStateException . Consulte o código abaixo para manipular duplicatas da lista também:

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

Aqui está a solução do StreamEx

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

É possível usar streams para fazer isso. Para remover a necessidade de usar explicitamente Collectors , é possível importar toMap estaticamente (conforme recomendado pelo Effective Java, terceira edição).

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

Vou escrever como converter lista em mapa usando genéricos e inversão de controle . Apenas método universal!

Talvez tenhamos uma lista de números inteiros ou uma lista de objects. Então a questão é a seguinte: qual deve ser a chave do mapa?

criar interface

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

agora usando inversão de controle:

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

Por exemplo, se tivermos objects de livro, essa class deve escolher a chave do 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)); 

Até serve esse propósito para mim

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

Isso pode ser feito de duas maneiras. Deixe a pessoa ser a class que vamos usar para demonstrar isso.

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

Deixe as pessoas serem a lista de pessoas a serem convertidas no mapa

1.Usando Simple foreach e uma Expressão Lambda na Lista

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

2.Usando coletores no stream definido na lista fornecida.

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