Sie können
verwenden %Vor% aber es wird Ihnen eine (funded) unchecked Warnung geben. Ihre Methode kann nicht das Versprechen halten, eine korrekt eingegebene Map<K, V>
für ein Array von beliebigen Objekten zurückzugeben, und noch schlimmer, sie wird nicht mit einer Ausnahme fehlschlagen, aber eine uneinheitliche Map automatisch zurückgeben, wenn Sie Objekte vom falschen Typ übergeben .
Eine sauberere, häufig verwendete Lösung ist
%Vor%Dies kann ohne Warnung kompiliert werden, da die Korrektheit zur Laufzeit überprüft wird. Der Aufrufcode muss angepasst werden:
%Vor% Neben der Notwendigkeit, die tatsächlichen Typen als Klassenliterale anzugeben, hat sie den Nachteil, dass sie generische Schlüssel- oder Werttypen nicht unterstützt (da sie nicht als Class
ausgedrückt werden können) und nur noch keine Kompilierungszeitsicherheit haben eine Laufzeitprüfung.
Es lohnt sich Java 9 anzusehen . Dort können Sie Folgendes tun:
%Vor% Dadurch wird eine unveränderliche Karte eines nicht angegebenen Typs anstelle von HashMap
erstellt, aber der interessante Punkt ist die API.
Es gibt eine Methode <K,V> Map.Entry<K,V> entry(K k, V v)
, die mit
<K,V> Map<K,V> ofEntries(Map.Entry<? extends K,? extends V>... entries)
kombiniert werden kann, um eine Karte variabler Länge zu erstellen (varargs sind jedoch immer noch auf 255 Parameter beschränkt).
Sie können eine ähnliche Sache implementieren:
%Vor% Die Convenience-Methode (n) of
werden auf die einzige Weise implementiert, dies kann mit type safety erfolgen: als überladene Methoden mit unterschiedlicher Anzahl von Argumenten, wie
(Java 9 macht den Schnitt bei zehn Mappings, wenn Sie mehr haben, müssen Sie die ofEntries(entry(k1, v1), …)
Variante verwenden).
Wenn Sie diesem Muster folgen, sollten Sie Ihren toMap
name beibehalten oder nur map
verwenden, anstatt " of
" aufzurufen, da Sie nicht die Map
-Schnittstelle schreiben.
Diese Überladungen sehen vielleicht nicht sehr elegant aus, aber sie lösen alle Probleme. Sie können den Code genau wie in Ihrer Frage schreiben, ohne Class
objects anzugeben, aber die Art der Kompilierungszeit Typsicherheit und sogar die Ablehnung von Versuchen, sie mit einer ungeraden Anzahl von Argumenten aufzurufen, zu erhalten.
Sie müssen bei einer bestimmten Anzahl von Parametern einen Schnitt vornehmen, aber wie bereits erwähnt, unterstützen selbst Varargs keine unbegrenzten Parameter. Und das ofEntries(entry(…), …)
Formular ist nicht so schlecht für größere Karten.
Der Kollektor Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)
gibt einen unspezifizierten Kartentyp zurück, der möglicherweise sogar unveränderbar ist (obwohl es in der aktuellen Version ein HashMap
ist). Wenn Sie sicherstellen möchten, dass eine HashMap
Instanz zurückgegeben wird, müssen Sie stattdessen Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1,v2)->{throw new IllegalArgumentException("duplicate key");}, HashMap::new)
verwenden.
Genau das zu erreichen, was Sie wollen, funktioniert wahrscheinlich nicht für Karten, deren Schlüsseltyp sich von ihrem Werttyp unterscheidet. Dies liegt daran, dass die variable Arity-Deklaration von Java ( Object... entries
part) nur einen Typ unterstützt.
Einige Optionen kommen mir in den Sinn:
Sie könnten die Überprüfungen dynamisch durchführen und eine unzulässige Argumentausnahme auslösen, wenn die Werte nicht übereinstimmen. Aber Sie werden den Compiler-Typ-Check verlieren.
Sie könnten eine Pair
-Klasse definieren und ein wenig mit statischem Import spielen, um fast das zu erreichen, was Sie wollen:
z. B .:
%Vor%Hier ist meine Idee von JDK 8 stream:
%Vor%Wenn Sie die Drittanbieterbibliothek AbacusUtil nicht stören, könnte der Code folgendermaßen vereinfacht werden:
%Vor%Und ich denke, der effizienteste Weg ist eine for-Schleife, wenn Sie die Stream-API nicht besonders verfolgen
%Vor%Tags und Links java arrays java-8 hashmap java-stream