5

Ich benutze einen rekursiven Baum von Hashmaps, speziell Hasmapmap, wobei Objekt ein Verweis auf eine andere Hashmap ist und so weiter. Dies wird um einen rekursiven Algorithmus übergeben werden:Java Generics Type Sicherheitswarnung mit rekursivem Hashmap

foo(String filename, Hashmap<String, Object> map) 
{ 
    //some stuff here 
    for (Entry<String, Object> entry : map.entrySet()) 
    { 
     //type warning that must be suppressed 
     foo(entry.getKey(), (HashMap<String, Object>)entry.getValue()); 
    } 
} 

Ich weiß sicher, Object ist vom Typ Hashmap<String, Object> aber sind irritiert, dass ich die Warnung @SuppressWarnings("unchecked") mit zu unterdrücken.

Ich werde mit einer Lösung zufrieden sein, die entweder eine assert(/*entry.getValue() is of type HashMap<String, Object>*/) tut oder eine Ausnahme auslöst, wenn dies nicht der Fall ist. Ich bin die Generics-Route für Kompilierung Typ Sicherheit gegangen und wenn ich die Warnung unterdrücken, dann schlägt es den Zweck.

Vielen Dank für Ihre Kommentare, ksb

Antwort

5

Dies ist möglich, ein gattungsgemäßes Verfahren mit einer rekursiven Variable. Versuchen Sie folgendes:

public <T extends Map<String, T>> void foo(String filename, T map) { 
    //some stuff here 
    for (Map.Entry<String, T> entry : map.entrySet()) { 
     foo(entry.getKey(), entry.getValue()); 
    } 
} 

Sollte Kompilieren ohne Warnungen gut.

Wenn Sie jedoch die Kontrolle über die Karte haben und Ihre eigene Klasse ersetzen können, könnte es besser sein, einen Klassenknoten zu erstellen (dieser sieht für mich wie ein Baum aus), der stattdessen eine Map enthält. Etwas wie:

public class Node { 
    private Map<String, Node> children; 

    ... 
    // accessor methods to retrieve children ... 
} 

Und haben foo stattdessen eine Node als zweites Argument nehmen. Nur ein Vorschlag.

+0

Lieber Waxwing, Ich habe meinen zweiten Vorschlag umgesetzt, weil sich herausstellt, dass ich dem "Knoten" zusätzliche Dinge hinzufügen muss, als nur einen Verweis auf einen anderen Hashmapp. Es fühlt sich auch viel natürlicher an. Ich bin gerade mit Java in den Griff, so kann ich Ihren ersten Vorschlag nicht verstehen - die "T erweitert Karte " Teil. Nochmals vielen Dank, KSB –

5

Sie diese Klasse statt HashMap verwenden:

public class RecursiveHashMap extends HashMap<String,RecursiveHashMap> 
{ 
} 
+0

Sehr geehrte Ha, Ich verstehe nicht wirklich, warum das funktioniert (Java noob), also habe es nicht ausprobiert. Ich gehe mit der Node-Lösung von Waxwing. Danke, KSB –

+0

Yeap, creating 'Node' Klasse (aka Composite-Muster) ist viel besser als' HashMap's. –

1

Ihre Datenstruktur sieht so aus, als ob Sie Bäume von Dateien (Dateinamen) damit darstellen möchten. Ich würde nicht empfehlen, dies mit HashMap als Knotentyp zu tun.

Ich würde vorschlagen, das zusammengesetzte Muster verwenden (siehe Wikipedia), vereinfachte Code:

abstract class Node 
{ 
    String filename; 
    Node(String filename) { this.filename = filename; } 
    abstract foo(); 
} 

class FileNode implements Node 
{ 
    FileNode(String filename) { super(filename); } 
    foo() { ... } 
} 

class DirectoryNode implements Node 
{ 
    Set<Node> children; 
    DirectoryNode(String filename, Set<Node> children) 
    { 
    super(filename); 
    this.children = children; 
    } 
    foo() 
    { 
    for (Node child : children) child.foo(); 
    } 
} 

Die HashMap Sie auf das Set mit wurden in DirectoryNode erscheinen läuft darauf hinaus.

+0

Danke für den Gedanken. Meine Entitäten können nicht natürlich in zwei Knotentypen unterteilt werden, d. H. Verzeichnis und Dateien. Alle von ihnen sind "Dateien". Insbesondere muss ich die gleiche Verarbeitung foo() auf allen Ebenen der Hierarchie vornehmen. Ich bin nicht in der Lage, Ihren Code zu erweitern, um dies zu erreichen. –

+0

Warum nicht? Sie können den gesamten benötigten Code in DirectoryNode.foo() einfügen. Sie könnten den Code auch in Node einfügen.foo() und dann super.foo() auf DirectoryNode.foo() aufrufen. Dann wäre Knoten Ihre Datei. – Wolfgang

+0

Ich sehe, was Sie sagen: Setzen Sie den gemeinsamen Code in Node (foo ist nicht mehr abstrakt) und haben Sie Datei und Verzeichnis Aufruf super (Dateiname). Werde mich daran erinnern. Danke, ksb –