Java Generics Type带有递归Hashmap的安全警告

时间:2010-03-14 21:13:30

标签: java generics hashmap type-safety recursive-datastructures

我正在使用一个递归的hashmaps树,特别是Hashmap map,其中Object是对另一个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());
    }
}

我确定Object的类型为Hashmap<String, Object>但我很恼火,因为我必须使用@SuppressWarnings("unchecked")取消警告。

我会对一个解决方案感到满意,该解决方案可以执行assert(/*entry.getValue() is of type HashMap<String, Object>*/),也可以在异常时抛出异常。我沿着Generics路线走了编译类型安全,如果我压制警告那么它就会失败。

感谢您的评论, KSB

3 个答案:

答案 0 :(得分:5)

您可以使用此类而不是HashMap:

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

答案 1 :(得分:5)

这可以使用带有递归类型变量的泛型方法。请尝试以下方法:

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

在没有任何警告的情况下编译正常。

但是,如果您可以控制地图,并且可以替换您自己的类,那么创建一个类Node(这对我来说就像一棵树)可能更具可读性,包含 a改为映射。类似的东西:

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

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

foo取代Node作为第二个参数。只是一个建议。

答案 2 :(得分:1)

您的数据结构看起来像是要用它来表示文件树(文件名)。我不建议使用HashMap作为节点类型。

我建议使用复合模式(参见维基百科),简化代码:

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

您使用的HashMap归结为出现在DirectoryNode中的Set。