Question

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 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

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top