2010-03-14 14 views
5

Estoy usando un árbol recursivo de hashmaps, específicamente el mapa Hashmap donde Object es una referencia a otro Hashmap, y así sucesivamente. Esto se pasa alrededor de un algoritmo recursivo:Tipo de genéricos de Java Advertencia de seguridad con Hashmap recursivo

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()); 
    } 
} 

que sé con seguridad es de tipo ObjectHashmap<String, Object> pero irritan que tengo que suprimir la advertencia usando @SuppressWarnings("unchecked").

Voy a estar satisfecho con una solución que hace ya sea un assert(/*entry.getValue() is of type HashMap<String, Object>*/) o lanza una excepción cuando no lo es. Bajé por la ruta de Generics para seguridad de compilación y, si reprimo la advertencia, se frustra el objetivo.

Gracias por sus comentarios, KSB

Respuesta

5

Esto es posible utilizando un método genérico con una variable de tipo recursivo. Intente lo siguiente:

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()); 
    } 
} 

Debe compilar bien sin ningún tipo de advertencias.

Sin embargo, si usted tiene el control del mapa, y puede sustituir su propia clase, puede ser que sea más legible para hacer un nodo de clase (esto se parece a un árbol para mí), que contiene un mapa en su lugar. Algo así como:

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

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

Y tienen foo tomar un Node como segundo argumento en su lugar. Sólo una sugerencia.

+0

querido waxwing, Terminé implementando su segunda sugerencia porque resulta que necesito agregar cosas adicionales al "nodo" que solo una referencia a otro hashmap. También se siente mucho más natural. Estoy empezando a comprender Java, por lo que no puedo entender su primera sugerencia: la parte "T extends Map ". Gracias una vez más, KSB –

5

Puede utilizar esta clase en lugar de HashMap:

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

Querido Ha, Realmente no entiendo por qué esto podría funcionar (Java noob), por lo tanto no lo probé. Voy con la solución de Nodo de waxwing. Gracias, KSB –

+0

Yeap, la creación de la clase 'Node' (también conocida como patrón Compuesto) es mucho mejor que la de' HashMap'. –

1

Su estructura de datos parece que quiere representar árboles de archivos (nombres de archivos) con ella. No recomendaría hacer esto con HashMap como el tipo de nodo.

me gustaría sugerir a utilizar el patrón de material compuesto (ver Wikipedia), el código simplificado:

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(); 
    } 
} 

El HashMap que estaba utilizando se reduce al conjunto que aparece en DirectoryNode.

+0

Gracias por la idea. Mis entidades no pueden dividirse de forma natural en dos tipos de nodos, es decir, Directorio y Archivos. Todos ellos son "Archivos". Específicamente, necesito hacer el mismo procesamiento foo() en todas las capas de la jerarquía. No puedo extender tu código para lograr esto. –

+0

¿Por qué no? Puede poner todo el código que necesita en DirectoryNode.foo(). También podría poner el código en Nodo.foo() y luego llama a super.foo() en DirectoryNode.foo(). Entonces el nodo sería tu archivo. – Wolfgang

+0

Veo lo que dice: inserte el código común dentro de Node (foo ya no es abstracto) y haga que File and Directory llame a super (filename). Te acordaré de eso. Gracias, ksb –

Cuestiones relacionadas