2017-03-10 4 views
2

Der folgende Code ist ein Pseudo-Code, der zeigt, was ich will erreichen basiert aufzuspalten:Sammler Mit Dampf in Listen auf Klasse in Java

Map<Class<?>, List<?>> map = Stream.of(1, "2").collect(Collectors.groupingBy(Object::getClass)); 
List<Integer> ints = map.get(Integer.class); 
List<String> strings = map.get(String.class); 

Die oben ist ein vereinfachter Code. Was ich will ist, dass ich eine Eingabeliste habe, ich möchte sie in mehrere Listen basierend auf der Klasse der Objekte aufteilen.

Jedoch der Code oben kompiliert nicht, ich frage mich, wie Sie es beheben können?

+2

"der obige Code kompiliert nicht" wahrscheinlich, weil ein Problem vorliegt. Ernsthaft, wenn Sie Fehler haben, posten Sie sie, anstatt zu sagen, dass Sie Fehler haben. – Holger

Antwort

5

Die erste Zeile von befestigt werden kann List<?> zu List<Object> Wechsel:

Map<Class<?>, List<Object>> map = Stream.of(1, "2") 
     .collect(Collectors.groupingBy(Object::getClass)); 

Die folgenden Zeilen sind problematischer. Ich denke nicht, dass es eine Möglichkeit gibt, diese generische Beziehung in Java zu definieren. Sie werden einen hässlichen, unsicheren Guss verwenden müssen:

List<Integer> ints = (List)map.get(Integer.class); 
List<String> strings = (List)map.get(String.class); 

Wenn Sie es sicherer und benutzerfreundlicher machen mögen, können Sie es hinter einer benutzerdefinierten Klasse verstecken:

class TypeToListMap { 
    private Map<Class<?>, List<Object>> map = ... 

    public <T> List<T> get(Class<T> key) { 
     @SuppressWarnings("unchecked") 
     List<T> result = (List<T>)map.get(key); 
     return result; 
    } 
} 
+2

Die ' Liste bekommen (Klasse )' Methode ist der beste Weg. Es versteckt nicht nur die ungeprüfte Operation; es kombiniert es mit der Operation, die die Korrektheit sicherstellen soll, d. h. die 'Klasse' als Suchschlüssel verwenden. Es reduziert also die Fehler, die Sie machen können. – Holger

1

können Sie List<Object> anstelle von List<?>:

Map<Class<?>, List<Object>> map = Stream.of(1, "2") 
    .collect(Collectors.groupingBy(Object::getClass)); 
List<Object> ints = map.get(Integer.class); 
List<Object> strings = map.get(String.class); 
1

Nun, die Typ:

Stream.of(1, "2"); 

ist eigentlich:

Stream<?> stream = Stream.of(1, "2"); 

Und der einzige legale Ersatz für ? wäre in diesem Fall Object.

Wegen Typ löschen ? wäre Objekt.

Es ist wie Sie müssen den Typ Ihrer Liste zur Laufzeit mit Generika deklarieren. Es ist wie dies zu tun:

T x; 
List<x.getClass()> list = ...; // can't do that 

Sie einen Hack hier tun können, und zweimal werfen :)

@SuppressWarnings("unchecked") 
    List<Integer> ints = (List<Integer>) (List<?>) map.get(Integer.class); 
1

Eigentlich kann man nur werfen Ergebnisse. Listen sollten eigentlich aus Objekten der benötigten Typen bestehen, also sollte es kein Problem geben. Sie erhalten jedoch möglicherweise eine Compiler-Warnung (wenn Sie dem Compiler angegeben haben, dass Sie ungeprüfte Cast-Warnungen erhalten möchten).

+0

Und tatsächlich kann es sein, müssen Sie Löschen verwenden: 'Liste = (Liste) ...' –