Vor kurzem habe ich Gespräch mit einem Kollegen über das, was den optimalen Weg zu konvertieren wäre List
zu Map
in Java und wenn es spezifische Vorteile, dies zu tun.
Ich möchte einen optimalen Konvertierungsansatz kennen und würde mich sehr freuen, wenn mich jemand führen kann.
Ist das ein guter Ansatz:
List<Object[]> results;
Map<Integer, String> resultsMap = new HashMap<Integer, String>();
for (Object[] o : results) {
resultsMap.put((Integer) o[0], (String) o[1]);
}
Antworten:
Angenommen, jedes Element verfügt über eine
getKey()
Methode, die einen Schlüssel des richtigen Typs zurückgibt.quelle
getKey()
auf einen bestimmten Parameter einstellen ?getKey()
war willkürlich.Mit Java-8Sie können dies in einer Zeile mithilfe von Streams und der
Collectors
Klasse tun .Kurze Demo:
Ausgabe:
Wie in den Kommentaren erwähnt, können Sie
Function.identity()
anstelle von verwendenitem -> item
, obwohl ichi -> i
ziemlich explizit finde .Um vollständig zu sein, beachten Sie, dass Sie einen binären Operator verwenden können, wenn Ihre Funktion nicht bijektiv ist. Betrachten wir zum Beispiel dies
List
und die Zuordnungsfunktion, die für einen int-Wert das Ergebnis davon modulo 3 berechnet:Wenn Sie diesen Code ausführen, wird eine Fehlermeldung angezeigt
java.lang.IllegalStateException: Duplicate key 1
. Dies liegt daran, dass 1% 3 gleich 4% 3 ist und daher bei gegebener Schlüsselzuordnungsfunktion denselben Schlüsselwert hat. In diesem Fall können Sie einen Zusammenführungsoperator angeben.Hier ist eine, die die Werte summiert;
(i1, i2) -> i1 + i2;
das kann durch die Methodenreferenz ersetzt werdenInteger::sum
.welches jetzt ausgibt:
Ich hoffe es hilft! :) :)
quelle
Function.identity()
stattitem -> item
Function.identity()
kehrt zurückt -> t;
.::getKey
.Nur für den Fall, dass diese Frage nicht als Duplikat geschlossen wird, ist die richtige Antwort die Verwendung von Google Collections :
quelle
Mit Java 8 können Sie Folgendes tun:
Value
kann jedes Objekt sein, das Sie verwenden.quelle
Seit Java 8 wird die Antwort von @ZouZou mit dem
Collectors.toMap
Kollektor sicherlich der idiomatische Weg, um dieses Problem zu lösen.Und da dies eine so häufige Aufgabe ist, können wir daraus ein statisches Dienstprogramm machen.
Auf diese Weise wird die Lösung wirklich zu einem Einzeiler.
Und so würden Sie es auf einem verwenden
List<Student>
:quelle
A
List
undMap
sind konzeptionell unterschiedlich. AList
ist eine bestellte Sammlung von Gegenständen. Die Elemente können Duplikate enthalten, und ein Element hat möglicherweise kein Konzept für eine eindeutige Kennung (Schlüssel). EINMap
hat Werte, die Schlüsseln zugeordnet sind. Jeder Schlüssel kann nur auf einen Wert zeigen.Abhängig von Ihren
List
Artikeln kann es daher möglich sein, sie in a umzuwandelnMap
.List
Haben Ihre Artikel keine Duplikate? Hat jeder Artikel einen eindeutigen Schlüssel? Wenn ja, dann ist es möglich, sie in eine zu setzenMap
.quelle
Alexis hat bereits eine Antwort in Java 8 mit der Methode veröffentlicht
toMap(keyMapper, valueMapper)
. Gemäß Dokument für diese Methodenimplementierung:Wenn wir also an einer bestimmten Implementierung der
Map
Schnittstelle interessiert sind,HashMap
können wir das überladene Formular wie folgt verwenden:Obwohl entweder mit
Function.identity()
oder ini->i
Ordnung ist , aber es scheintFunction.identity()
statti -> i
Macht sparte etwas Speicher gemäß diesem Stand der Antwort .quelle
Es gibt auch eine einfache Möglichkeit, dies mit Maps.uniqueIndex (...) zu tun. von Google zuGuave Bibliotheken
quelle
Universelle Methode
quelle
converter
Parameter in der Methode übergeben?Ohne Java-8 können Sie dies in einzeiligen Commons-Sammlungen und in der Closure-Klasse tun
quelle
Je nachdem, was Sie erreichen möchten, fallen Ihnen viele Lösungen ein:
Jedes Listenelement ist Schlüssel und Wert
Listenelemente haben etwas zum Nachschlagen, vielleicht einen Namen:
Listenelemente können nachgeschlagen werden, und es gibt keine Garantie dafür, dass sie eindeutig sind: Verwenden Sie Googles MultiMaps
Geben Sie allen Elementen die Position als Schlüssel:
...
Es kommt wirklich darauf an, was Sie erreichen wollen.
Wie Sie den Beispielen entnehmen können, ist eine Karte eine Zuordnung von einem Schlüssel zu einem Wert, während eine Liste nur eine Reihe von Elementen mit jeweils einer Position ist. Sie sind also einfach nicht automatisch konvertierbar.
quelle
Hier ist eine kleine Methode, die ich genau für diesen Zweck geschrieben habe. Es verwendet Validate from Apache Commons.
Fühlen Sie sich frei, es zu benutzen.
quelle
Sie können die Streams-API von Java 8 nutzen.
Weitere Informationen finden Sie unter: http://codecramp.com/java-8-streams-api-convert-list-map/
quelle
Ein Java 8-Beispiel zum Konvertieren eines
List<?>
Objekts in einMap<k, v>
:Code kopiert von:
https://www.mkyong.com/java8/java-8-convert-list-to-map/
quelle
Wie bereits gesagt, haben wir in Java-8 die prägnante Lösung von Collectors:
Außerdem können Sie mehrere Gruppen verschachteln, indem Sie eine andere groupingBy-Methode als zweiten Parameter übergeben:
Auf diese Weise erhalten wir eine mehrstufige Karte wie folgt:
Map<key, Map<key, List<Item>>>
quelle
Verwenden von Java-8-Streams
quelle
Ich mag die Antwort von Kango_V, aber ich denke, sie ist zu komplex. Ich denke, das ist einfacher - vielleicht zu einfach. Wenn Sie dazu neigen, können Sie String durch einen generischen Marker ersetzen und ihn für jeden Schlüsseltyp verwenden.
So verwendet:
quelle
Apache Commons MapUtils.populateMap
Wenn Sie Java 8 nicht verwenden und aus irgendeinem Grund keine explizite Schleife verwenden möchten, versuchen Sie es mit
MapUtils.populateMap
Apache Commons.MapUtils.populateMap
Angenommen, Sie haben eine Liste von
Pair
s.Und Sie möchten jetzt eine Karte des
Pair
Schlüssels desPair
Objekts.gibt Ausgabe:
Davon abgesehen ist eine
for
Schleife vielleicht leichter zu verstehen. (Dies unten gibt die gleiche Ausgabe):quelle