2017-04-07 6 views
3

Ich möchte ein Map mit mehreren Listen, jeder von ihnen besteht aus Comparable Objekte, aber nicht immer die gleiche, so könnte es eine List von Doubles und List von Strings, etc sein ...Generika Karte mit Listen von Vergleichbare

Map<String, List<Comparable<?>>>

Leider ist die Map wie oben definiert sind nicht sinnvoll, da die Elemente in jeder List nicht verglichen werden können. Deshalb hatte ich einen Typ-Parameter auf die Klasse zu betrügen und vorstellen:

class MyClass<T extends Comparable<? super T>> { 
    Map<String, List<T>> myMap; 
} 

Das ist nicht ganz korrekt ist, weil nicht alle Listen der vom gleichen Typ sind. Aber es funktioniert, das einzige, was ich tun muss, ist eine Typumwandlung zu T, wenn ich eine Double zu einer Liste von Doubles oder String zu einer Liste von Zeichenfolgen hinzufügen. Ich stelle sicher, dass jeder Typ nur zu Listen des richtigen Typs hinzugefügt wird.

Gibt es einen besseren Weg, um dieses Problem zu lösen? Die Alternative ist eine Map für jede Art von List zu haben. Aber das würde den Code nur hässlicher machen, und das einzige, was ich mit den Listen mache, ist sie zu sortieren und sie in einen DB als String-Werte einzufügen, daher rufe ich nur toString über die Vergleichswerte an.

+1

Sie verwenden ein [ 'checkedList'] (https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#checkedList-java.util.List- java.lang.Class-) um das Fehlerrisiko zu reduzieren. – shmosel

+2

Da Sie dem Java-Compiler nicht statisch mitteilen können, welche Art von Elementen in der 'Liste' enthalten ist, können Sie nicht einmal sicherstellen, dass Elemente in einer der Listen miteinander vergleichbar sind. Kurz gesagt, Sie sollten dies entweder nicht tun oder akzeptieren, dass Sie die statische Typprüfung, z. indem Sie es als 'Map >' deklarieren, indem Sie den generischen Rohtyp 'Comparable' verwenden. Akzeptieren Sie dann die Compiler-Warnungen, in denen Ihnen mitgeteilt wird, dass Sie die statische Typprüfung umgehen. – Andreas

+0

@smosbel wow, wieso habe ich noch nie davon gehört? Danke :) – Roland

Antwort

1

Sie können List<Object> verwenden, um es generisch und diesen Zweck zu machen.
Sie möchten vielleicht instance of überprüft für einige bestimmte Datentypen in der Liste.

Map<String, List<Object>> map = new HashMap<>(); 

List<Object> list; 

list = new ArrayList<>(Arrays.asList(new Object[] { 1, 2, 3.45, "dev", 'A', true, false })); 
map.put("key1", list); 

list = new ArrayList<>(Arrays.asList(new Object[] { false, 100, 5.1234f, "user", 'Z', true })); 
map.put("key2", list); 

for (Map.Entry<String, List<Object>> entry : map.entrySet()) { 
    System.out.println(entry.getKey() + " => " + entry.getValue()); 
} 

Ausgang:
key1 => [1, 2, 3.45, dev, A, true, false] key2 => [false, 100, 5.1234, user, Z, true]

0

Vom docs of java generic wildcard heißt es: (?)

In generischem Code, das Fragezeichen, die so genannte Wildcard, stellt eine unbekannte Art.

Und auch:

Der Platzhalter wird nie als Typargument für einen generischen Methodenaufruf, eine generische Klasseninstanz Schöpfung oder einen übergeordneten Typ verwendet.

Also, wenn Sie die folgende Erklärung:

List<?> list = new ArrayList<>(); 

Dann können Sie nichts list hinzufügen, weil Sie nur Compiler gesagt, dass „ich nicht die Art von Objekten, die wissen wollen in list gesetzt werden "

So Ihr Code List<Comparable<?>> bedeutet, dass‚ich eine Liste wollen vergleichbare Objekte enthält, aber ich weiß nicht seine Art‘, die für Compiler nicht in Ordnung ist, weil der Compiler wissen müssen die Typinfo für ihre Arbeit.

verwenden Liste enthält alle Comparable Objekte, Sie upper bounded wildcards wie verwenden:

Map<String, List<? extends Comparable>> map = new HashMap<>(); 

Dann setzen Sie sind fein jede comparable Liste als Wert für diese Karte:

public static void main(String[] args) { 
    Map<String, List<? extends Comparable>> map = new HashMap<>(); 
    List<Integer> as = new ArrayList<>(); 
    as.add(1); 
    as.add(5); 
    as.add(3); 

    map.put("as", as); 

    List<String> bs = new ArrayList<>(); 
    bs.add("hello"); 
    bs.add("world"); 
    bs.add("generics"); 

    map.put("bs", bs); 
} 

Schließlich I Ich nehme an, Sie werden sich für inheritance and subtypes in generics interessieren, hoffe, dass Ihnen das weiterhelfen könnte.

+0

Sie haben seltene Arten drin. Das wird zu weiteren SO Fragen führen ... –

0

Dies sieht ein bisschen wie eine heterogene Karte aus. Was machen Sie eigentlich mit Ihrer Vergleichsliste außer Vergleiche?

Wenn Sie jedoch möchten, dass die Listen unterschiedliche Typen haben, sollte die Indirektion um die List herum sein.

public final class SortableList<T extends Comparable<? super T>> { 
    private final List<T> elements; 
    public SortableList(List<T> elements) { 
     this.elements = elements; 
    } 
    public List<T> elements() { 
     return elements; 
    } 
} 

... 

Map<String,SortableList<?>> sortables; 
... 
Comparable<?> colaMax = Collections.max(sortables.get("shirley").elements());