Java Generics Type Safety warning with recursive Hashmap
I'm using a recursive tree of hashmaps, specifically Hashmap map where Object is a reference to another Hashmap and so on. This will be passed 开发者_JAVA技巧around a recursive algorithm:
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());
}
}
I know for sure Object
is of type Hashmap<String, Object>
but am irritated that I have to suppress the warning using @SuppressWarnings("unchecked")
.
I'll be satisfied with a solution that does either a assert(/*entry.getValue() is of type HashMap<String, Object>*/)
or throws an exception when it isn't. I went down the Generics route for compile type safety and if I suppress the warning then it defeats the purpose.
Thank you for your comments, ksb
This is possible using a generic method with a recursive type variable. Try the following:
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());
}
}
Should compile fine without any warnings.
However, if you have control of the map, and can substitute your own class, it might be more readable to make a class Node (this looks like a tree to me), that contains a Map instead. Something like:
public class Node {
private Map<String, Node> children;
...
// accessor methods to retrieve children ...
}
And have foo
take a Node
as its second argument instead. Just a suggestion.
You can use this class instead of HashMap:
public class RecursiveHashMap extends HashMap<String,RecursiveHashMap>
{
}
Your data structure looks like you want to represent trees of files (filenames) with it. I'd not recommend to do this with HashMap as the node type.
I'd suggest to use the composite pattern (see wikipedia), simplified 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();
}
}
The HashMap you were using boils down to the Set appearing in DirectoryNode.
精彩评论