it-swarm.com.de

Java 8 Liste <V> in Karte <K, V>

Ich möchte eine Liste von Objekten mit Java 8-Streams und Lambdas in eine Map übersetzen.

So würde ich es in Java 7 und darunter schreiben.

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

Ich kann dies leicht mit Java 8 und Guava erreichen, aber ich würde gerne wissen, wie man dies ohne Guava macht.

In Guave:

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

Und Guava mit Java 8-Lambdas.

private Map<String, Choice> nameMap(List<Choice> choices) {
    return Maps.uniqueIndex(choices, Choice::getName);
}
795
Tom Cammann

Basierend auf Collectors Dokumentation es ist so einfach wie:

Map<String, Choice> result =
    choices.stream().collect(Collectors.toMap(Choice::getName,
                                              Function.identity()));
1209
zapl

Wenn Ihr SchlüsselNICHTgarantiert eindeutig für alle Elemente in der Liste ist, sollten Sie ihn in einen Map<String, List<Choice>> anstelle eines Map<String, Choice> konvertieren.

Map<String, List<Choice>> result =
 choices.stream().collect(Collectors.groupingBy(Choice::getName));
261
Ulises

Verwenden Sie getName () als Schlüssel und die Auswahl selbst als Wert der Map:

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

Hier ist eine weitere, falls Sie Collectors.toMap () nicht verwenden möchten

Map<String, Choice> result =
   choices.stream().collect(HashMap<String, Choice>::new, 
                           (m, c) -> m.put(c.getName(), c),
                           (m, u) -> {});
18
Emre Colak

Bei den meisten Antworten wird ein Fall nicht angezeigt, wenn die Liste doppelte Elemente enthält . In diesem Fall wird IllegalStateException ausgegeben. Siehe den folgenden Code, um List-Duplikate zu behandeln ebenso:

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

Eine weitere Option auf einfache Weise

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

Wenn Sie zum Beispiel Objektfelder in eine Map konvertieren möchten:

Beispielobjekt:

class Item{
        private String code;
        private String name;

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

        //getters and setters
    }

Und Vorgang konvertieren List To 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));
13
Piotr R

Wenn Sie sich nicht für die Verwendung von Drittanbieter-Bibliotheken interessieren, verfügt AOLs cyclops-react -Lib (Offenlegung, dass ich einen Beitrag geleistet habe) über Erweiterungen für alle JDK Collection -Typen, einschließlich List und Map .

ListX<Choices> choices;
Map<String, Choice> map = choices.toMap(c-> c.getName(),c->c);
10
John McClean

Ich habe versucht, dies zu tun, und fand heraus, dass ich bei Verwendung der Antworten oben bei der Verwendung von Functions.identity() für den Schlüssel der Map dann Probleme mit der Verwendung einer lokalen Methode wie this::localMethodName hatte, die aufgrund von Tippproblemen tatsächlich funktioniert.

Functions.identity() macht in diesem Fall tatsächlich etwas mit der Typisierung, so dass die Methode nur funktioniert, indem Object zurückgegeben und ein Parameter von Object akzeptiert wird.

Um dieses Problem zu lösen, habe ich Functions.identity() eingestellt und stattdessen s->s verwendet.

Also, mein Code, in meinem Fall, um alle Verzeichnisse in einem Verzeichnis aufzulisten, und für jedes Verzeichnis den Namen des Verzeichnisses als Schlüssel für die Map verwenden und dann eine Methode mit dem Verzeichnisnamen aufrufen und eine Sammlung von Elementen zurückgeben, sieht folgendermaßen aus:

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

Sie können einen Stream der Indizes mit einem IntStream erstellen und dann in eine Map konvertieren:

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

Ich werde schreiben, wie man die Liste in eine Map umwandelt, indem man generics und die Inversion von control verwendet. Einfach universelle Methode!

Vielleicht Wir haben Liste von Ganzzahlen oder Liste von Objekten. Die Frage ist also: Was sollte der Schlüssel der Karte sein?

schnittstelle erstellen

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

jetzt mit Umkehrung der Kontrolle:

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

Wenn wir beispielsweise Objekte eines Buches haben, wählt diese Klasse den Schlüssel für die Karte 

public class BookKeyFinder implements KeyFinder<Long, Book> {
    @Override
    public Long getKey(Book e) {
        return e.getPrice()
    }
}
4
grep

Ich benutze diese Syntax

Map<Integer, List<Choice>> choiceMap = 
choices.stream().collect(Collectors.groupingBy(choice -> choice.getName()));
4
user2069723
Map<String, Set<String>> collect = Arrays.asList(Locale.getAvailableLocales()).stream().collect(Collectors
                .toMap(l -> l.getDisplayCountry(), l -> Collections.singleton(l.getDisplayLanguage())));
3
Kumar Abhishek

Hierfür können Streams verwendet werden. Um die Notwendigkeit der expliziten Verwendung von Collectors zu beseitigen, ist es möglich, toMap statisch zu importieren (wie von Effective Java empfohlen, dritte Ausgabe).

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
Konrad Borowski

Hier ist die Lösung von StreamEx

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

Dies kann auf zwei Arten erfolgen. Lassen Sie die Person die Klasse sein, mit der wir sie demonstrieren werden.

public class Person {

    private String name;
    private int age;

    public String getAge() {
        return age;
    }
}

Lassen Sie Personen die Liste der Personen sein, die in die Karte umgewandelt werden sollen

1.Verwenden Sie einfach foreach und einen Lambda-Ausdruck in der Liste

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

2.Verwenden von Collectors-Streams, die in der angegebenen Liste definiert sind.

 Map<Integer,List<Person>> mapPersons = 
           persons.stream().collect(Collectors.groupingBy(Person::getAge));
0
raja emani
List<V> choices; // your list
Map<K,V> result = choices.stream().collect(Collectors.toMap(choice::getKey(),choice));
//assuming class "V" has a method to get the key, this method must handle case of duplicates too and provide a unique key.
0
vaibhav
String array[] = {"ASDFASDFASDF","AA", "BBB", "CCCC", "DD", "EEDDDAD"};
    List<String> list = Arrays.asList(array);
    Map<Integer, String> map = list.stream()
            .collect(Collectors.toMap(s -> s.length(), s -> s, (x, y) -> {
                System.out.println("Dublicate key" + x);
                return x;
            },()-> new TreeMap<>((s1,s2)->s2.compareTo(s1))));
    System.out.println(map);

Den Schlüssel AA {12 = ASDFASDFASDF, 7 = EEDDDAD, 4 = CCCC, 3 = BBB, 2 = AA}

0
Ajay
Map<String,Choice> map=list.stream().collect(Collectors.toMap(Choice::getName, s->s));

Sogar diesen Zweck dient für mich,

Map<String,Choice> map=  list1.stream().collect(()-> new HashMap<String,Choice>(), 
            (r,s) -> r.put(s.getString(),s),(r,s) -> r.putAll(s));
0
Rajeev Akotkar
If every new value for the same key name has to be overidden
then below will be the code :

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

If all choices have to be grouped in a list for a name then 
below will be the code:

      public Map<String, Choice> 
       convertListToMap(List<Choice> choices) {
       return choices.stream().collect(Collectors.groupingBy(Choice::getName));
  }
0
Vaneet Kataria