Java 8 lista na mapie

Chcę przetłumaczyć listę obiektów na mapę używając strumieni Java 8 i Lambda.

Tak bym to napisał w Javie 7 i poniżej.

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

Mogę to łatwo osiągnąć za pomocą Java 8 i Guava, ale chciałbym wiedzieć, jak to zrobić bez Guava.

W Guawie:

private Map<String, Choice> nameMap(List<Choice> choices) {
    return Maps.uniqueIndex(choices, new Function<Choice, String>() {

        @Override
        public String apply(final Choice input) {
            return input.getName();
        }
    });
}

I guawa z Java 8 lambda.

private Map<String, Choice> nameMap(List<Choice> choices) {
    return Maps.uniqueIndex(choices, Choice::getName);
}
Author: Vitruvius, 2013-12-04

17 answers

Na podstawie Collectors Dokumentacja to tak proste jak:

Map<String, Choice> result =
    choices.stream().collect(Collectors.toMap(Choice::getName,
                                              Function.identity()));
 1092
Author: zapl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-11 15:17:11

Jeśli twój klucz jest , a nie gwarantowany, że będzie unikalny dla wszystkich elementów listy, powinieneś przekonwertować go na Map<String, List<Choice>> zamiast Map<String, Choice>

Map<String, List<Choice>> result =
 choices.stream().collect(Collectors.groupingBy(Choice::getName));
 221
Author: Ulises,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-30 00:05:59

Użyj getName () jako klucza i samego wyboru jako wartości Mapy:

Map<String, Choice> result =
    choices.stream().collect(Collectors.toMap(Choice::getName, c -> c));
 119
Author: Ole,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-10 10:41:13

Tutaj jest jeszcze jeden, jeśli nie chcesz używać kolektorów.toMap ()

Map<String, Choice> result =
   choices.stream().collect(HashMap<String, Choice>::new, 
                           (m, c) -> m.put(c.getName(), c),
                           (m, u) -> {});
 14
Author: Emre Colak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-19 18:38:37

Jeszcze jedna opcja w prosty sposób

Map<String,Choice> map = new HashMap<>();
choices.forEach(e->map.put(e.getName(),e));
 12
Author: Renukeswar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-07 07:02:40

Jeśli nie masz nic przeciwko używaniu bibliotek stron trzecich, lib cyclops-react AOL (disclosure I am a contributor) ma rozszerzenia dla wszystkich typów JDK Collection, w tym List i Map.

ListX<Choices> choices;
Map<String, Choice> map = choices.toMap(c-> c.getName(),c->c);
 9
Author: John McClean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-24 17:45:07

Na przykład, jeśli chcesz przekonwertować pola obiektu na mapę:

Przykładowy obiekt:

class Item{
        private String code;
        private String name;

        public Item(String code, String name) {
            this.code = code;
            this.name = name;
        }

        //getters and setters
    }

I operacja Konwertuj listę na mapę:

List<Item> list = new ArrayList<>();
list.add(new Item("code1", "name1"));
list.add(new Item("code2", "name2"));

Map<String,String> map = list.stream()
     .collect(Collectors.toMap(Item::getCode(), Item::getName()));
 8
Author: Piotr R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-20 13:06:07

Próbowałem to zrobić i stwierdziłem, że używając powyższych odpowiedzi, podczas używania {[1] } dla klucza do mapy, miałem problemy z używaniem lokalnej metody, takiej jak this::localMethodName, aby faktycznie działać z powodu problemów z wpisaniem.

Functions.identity() w rzeczywistości robi coś z typowaniem w tym przypadku, więc metoda działa tylko przez zwrócenie Object i zaakceptowanie param Object

Aby to rozwiązać, porzuciłem Functions.identity()i zamiast tego użyłem s->s.

Więc mój kod, w moim przypadku do listy wszystkich katalogów wewnątrz katalogu i dla każdego z nich użyj nazwy katalogu jako klucza do mapy, a następnie wywołaj metodę z nazwą katalogu i zwróć kolekcję elementów, wygląda następująco:

Map<String, Collection<ItemType>> items = Arrays.stream(itemFilesDir.listFiles(File::isDirectory))
.map(File::getName)
.collect(Collectors.toMap(s->s, this::retrieveBrandItems));
 7
Author: iZian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-08 10:43:55

Większość z wymienionych odpowiedzi pomija przypadek, gdy lista ma duplikaty pozycji . W takim przypadku odpowiedź rzuci IllegalStateException. Zobacz poniższy kod , aby również obsługiwać duplikaty listy :

public Map<String, Choice> convertListToMap(List<Choice> choices) {
    return choices.stream()
        .collect(Collectors.toMap(Choice::getName, choice -> choice,
            (oldValue, newValue) -> newValue));
  }
 7
Author: Sahil Chhabra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-17 06:45:35

Możesz utworzyć strumień indeksów za pomocą strumienia IntStream, a następnie przekonwertować je na mapę:

Map<Integer,Item> map = 
IntStream.range(0,items.size())
         .boxed()
         .collect(Collectors.toMap (i -> i, i -> items.get(i)));
 5
Author: Vikas Suryawanshi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-09 05:33:11

Używam tej składni

Map<Integer, List<Choice>> choiceMap = 
choices.stream().collect(Collectors.groupingBy(choice -> choice.getName()));
 4
Author: user2069723,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-24 19:31:05
Map<String, Set<String>> collect = Arrays.asList(Locale.getAvailableLocales()).stream().collect(Collectors
                .toMap(l -> l.getDisplayCountry(), l -> Collections.singleton(l.getDisplayLanguage())));
 3
Author: Kumar Abhishek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-24 16:55:43

Możliwe jest użycie strumieni do tego celu. Aby usunąć potrzebę jawnego używania Collectors, można zaimportować toMap statycznie (zgodnie z zaleceniami Effective Java, third edition).

import static java.util.stream.Collectors.toMap;

private static Map<String, Choice> nameMap(List<Choice> choices) {
    return choices.stream().collect(toMap(Choice::getName, it -> it));
}
 2
Author: Konrad Borowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-02 12:05:36

Napiszę jak przekonwertować listę na mapę używając generykówi inwersji sterowania. Po prostu uniwersalna metoda!

Może mamy listę liczb całkowitych lub listę obiektów . więc pytanie brzmi: jaki powinien być klucz mapy?

Utwórz interfejs

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

Teraz za pomocą inwersji sterowania:

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

Na przykład, jeśli mamy obiekty książki, klasa ta ma wybrać klucz dla mapy

public class BookKeyFinder implements KeyFinder<Long, Book> {
    @Override
    public Long getKey(Book e) {
        return e.getPrice()
    }
}
 1
Author: grep,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-14 00:59:37

Oto rozwiązanie przez StreamEx

StreamEx.of(choices).toMap(Choice::getName, c -> c);
 0
Author: user_3380739,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-09 03:51:27
Map<String,Choice> map=list.stream().collect(Collectors.toMap(Choice::getName, s->s));

Nawet służy temu celowi dla mnie,

Map<String,Choice> map=  list1.stream().collect(()-> new HashMap<String,Choice>(), 
            (r,s) -> r.put(s.getString(),s),(r,s) -> r.putAll(s));
 0
Author: Rajeev Akotkar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-26 01:52:16

Można to zrobić na dwa sposoby. Niech osoba będzie klasą, której będziemy używać, aby ją zademonstrować.

public class Person {

    private String name;
    private int age;

    public String getAge() {
        return age;
    }
}

Let person be the list of Persons to be converted to the map

1.Użycie prostego foreach i wyrażenia Lambda na liście

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

2.Korzystanie z kolektorów w Strumieniu zdefiniowanym na podanej liście.

 Map<Integer,List<Person>> mapPersons = 
           persons.stream().collect(Collectors.groupingBy(Person::getAge));
 0
Author: raja emani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-04 10:45:05