Ich erstelle ein Map
aus einem List
wie folgt:
List<String> strings = Arrays.asList("a", "bb", "ccc");
Map<String, Integer> map = strings.stream()
.collect(Collectors.toMap(Function.identity(), String::length));
Ich möchte die gleiche Iterationsreihenfolge wie in der beibehalten List
. Wie kann ich LinkedHashMap
mit den Collectors.toMap()
Methoden eine erstellen ?
java
collections
java-8
java-stream
Ashika Umanga Umagiliya
quelle
quelle
Supplier
,Accumulator
undCombiner
diecollect
Methode Ihrerstream
:)Antworten:
Die 2-Parameter-Version von
Collectors.toMap()
verwendet aHashMap
:public static <T, K, U> Collector<T, ?, Map<K,U>> toMap( Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper) { return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new); }
Um die 4-Parameter-Version zu verwenden , können Sie Folgendes ersetzen:
mit:
Collectors.toMap( Function.identity(), String::length, (u, v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); }, LinkedHashMap::new )
Oder um es ein bisschen sauberer zu machen, schreiben Sie eine neue
toLinkedMap()
Methode und verwenden Sie diese:public class MoreCollectors { public static <T, K, U> Collector<T, ?, Map<K,U>> toLinkedMap( Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper) { return Collectors.toMap( keyMapper, valueMapper, (u, v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); }, LinkedHashMap::new ); } }
quelle
mergeFunction
dass in der 4-Parameter-VersionCollectors.toMap()
keine Ahnung hat, welcher Schlüssel zusammengeführt wird, beideu
undv
sind die Werte. Die Nachricht über IllegalStateException ist also nicht so richtig.Map::put
, erhalten Sie (möglicherweise) unterschiedliche Werte für denselben Schlüssel. Durch die VerwendungMap::put
haben Sie indirekt ausgewählt, dass der erste Wert, auf den Sie stoßen, falsch ist. Ist es das, was der Endbenutzer will? Bist du sicher? Wenn ja, dann sicher verwendenMap::put
. Andernfalls sind Sie sich nicht sicher und können sich nicht entscheiden: Lassen Sie den Benutzer wissen, dass sein Stream zwei identischen Schlüsseln mit unterschiedlichen Werten zugeordnet ist. Ich hätte Ihre eigene Antwort kommentiert, aber sie ist derzeit gesperrt.Bieten Sie Ihren eigenen
Supplier
,Accumulator
undCombiner
:List<String> myList = Arrays.asList("a", "bb", "ccc"); // or since java 9 List.of("a", "bb", "ccc"); LinkedHashMap<String, Integer> mapInOrder = myList .stream() .collect( LinkedHashMap::new, // Supplier (map, item) -> map.put(item, item.length()), // Accumulator Map::putAll); // Combiner System.out.println(mapInOrder); // {a=1, bb=2, ccc=3}
quelle
map.put(..)
die falsch sind.In Kotlin
toMap()
ist die Ordnung erhalten.Hier ist seine Implementierung:
public fun <K, V> Iterable<Pair<K, V>>.toMap(): Map<K, V> { if (this is Collection) { return when (size) { 0 -> emptyMap() 1 -> mapOf(if (this is List) this[0] else iterator().next()) else -> toMap(LinkedHashMap<K, V>(mapCapacity(size))) } } return toMap(LinkedHashMap<K, V>()).optimizeReadOnlyMap() }
Die Verwendung ist einfach:
val strings = listOf("a", "bb", "ccc") val map = strings.map { it to it.length }.toMap()
Die zugrunde liegende Sammlung für
map
ist aLinkedHashMap
(die nach Einfügung sortiert ist).quelle
Einfache Funktion zum Zuordnen von Objekten zu bestimmten Feldern:
public static <T, E> Map<E, T> toLinkedHashMap(List<T> list, Function<T, E> someFunction) { return list.stream() .collect(Collectors.toMap( someFunction, myObject -> myObject, (key1, key2) -> key1, LinkedHashMap::new) ); } Map<String, MyObject> myObjectsByIdMap1 = toLinkedHashMap( listOfMyObjects, MyObject::getSomeStringField() ); Map<Integer, MyObject> myObjectsByIdMap2 = toLinkedHashMap( listOfMyObjects, MyObject::getSomeIntegerField() );
quelle