2010-03-14 92 views
5

我正在使用hashmaps的遞歸樹,特別是Hashmap映射,其中Object是對另一個Hashmap的引用等等。這將圍繞一個遞歸算法進行傳遞:Java泛型類型帶有遞歸哈希映射的安全警告

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

我知道肯定是ObjectHashmap<String, Object>型的,但我惱火,我要抑制使用@SuppressWarnings("unchecked")警告。

我會滿意於一個解決方案,該解決方案可以執行assert(/*entry.getValue() is of type HashMap<String, Object>*/)或者在不是時拋出異常。爲了編譯類型安全,我放下了泛型路由,如果我壓制警告,那麼它就會失敗。

謝謝您的意見, KSB

回答

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

應該在沒有任何警告的情況下正常編譯。然而,如果你有對地圖的控制,並且可以替換你自己的類,那麼製作類節點可能會更具可讀性(這看起來像是一棵樹),包含a代替。喜歡的東西:

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

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

而且具有foo採取Node作爲第二個參數來代替。只是一個建議。

+0

親愛的蠟燭, 我結束了實現你的第二個建議,因爲事實證明我需要添加額外的東西到「節點」,而不僅僅是對另一個散列表的引用。它也感覺更自然。 我剛剛與Java交手,所以無法理解你的第一個建議 - 「T擴展地圖」部分。 再次感謝你, KSB – 2010-03-15 01:11:11

5

你可以使用這個類來代替HashMap中的:

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

親愛的哈, 真的不明白爲什麼這可能會工作(Java noob),因此沒有嘗試過。我正在使用waxwing的Node解決方案。 謝謝, KSB – 2010-03-15 01:13:38

+0

Yeap,創建'Node'類(aka複合模式)比'HashMap'更好。 – 2010-03-15 08:05:45

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。

+0

感謝您的想法。我的實體不能自然地分爲兩個節點類型,即目錄和文件。他們都是「文件」。具體而言,我需要在層次結構的所有層執行相同的處理foo()。我無法擴展您的代碼來完成此操作。 – 2010-03-15 00:56:55

+0

爲什麼不呢?您可以將所有需要的代碼放入DirectoryNode.foo()中。你也可以把代碼放到Node中。foo()然後在DirectoryNode.foo()上調用super.foo()。然後Node就是你的文件。 – Wolfgang 2010-03-15 15:37:32

+0

我明白你的意思了:將公共代碼放在Node中(foo不再是抽象的)並且具有文件和目錄調用超級(文件名)。會記得那一個。 謝謝,ksb – 2010-03-15 19:51:51