Aviso de segurança do tipo java genéricos com hashmap recursivo
-
20-09-2019 - |
Pergunta
Estou usando uma árvore recursiva de hashmaps, especificamente mapa de hashmap, onde o objeto é uma referência a outro hashmap e assim por diante. Isso será passado em torno de um algoritmo 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());
}
}
Eu sei com certeza Object
é do tipo Hashmap<String, Object>
mas estou irritado por ter que suprimir o aviso usando @SuppressWarnings("unchecked")
.
Ficarei satisfeito com uma solução que faça um assert(/*entry.getValue() is of type HashMap<String, Object>*/)
ou joga uma exceção quando não é. Fiz a rota genérica para a segurança do tipo compilar e, se suprimir o aviso, ele derrota o objetivo.
Obrigado por seus comentários, KSB
Solução
Isso é possível usando um método genérico com uma variável de tipo recursivo. Experimente o seguinte:
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());
}
}
Deve compilar bem sem nenhum aviso.
No entanto, se você tiver controle do mapa e pode substituir sua própria classe, pode ser mais legível para fazer um nó de classe (isso parece uma árvore para mim), que contém um mapa em vez disso. Algo como:
public class Node {
private Map<String, Node> children;
...
// accessor methods to retrieve children ...
}
E tem foo
dê uma Node
como seu segundo argumento. Apenas uma sugestão.
Outras dicas
Você pode usar esta classe em vez de hashmap:
public class RecursiveHashMap extends HashMap<String,RecursiveHashMap>
{
}
Sua estrutura de dados parece que você deseja representar árvores de arquivos (nomes de arquivos) com ele. Eu não recomendo fazer isso com o hashmap como o tipo de nó.
Eu sugeriria usar o padrão composto (consulte a Wikipedia), 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();
}
}
O hashmap que você estava usando furúnculos no conjunto aparecendo no DirectoryNode.