2010-03-14 26 views
5

Tôi đang sử dụng một cây đệ quy của hashmaps, cụ thể là bản đồ Hashmap nơi Object là một tham chiếu đến Hashmap khác và vân vân. Điều này sẽ được thông qua xung quanh một thuật toán đệ quy:Java Generics Type Cảnh báo an toàn với đệ quy 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()); 
    } 
} 

Tôi biết chắc chắn Object là loại Hashmap<String, Object> nhưng tôi bị kích thích mà tôi phải ngăn chặn cảnh báo sử dụng @SuppressWarnings("unchecked").

Tôi sẽ hài lòng với giải pháp thực hiện hoặc là assert(/*entry.getValue() is of type HashMap<String, Object>*/) hoặc ném ngoại lệ khi không. Tôi đã đi xuống các tuyến đường Generics cho an toàn loại biên dịch và nếu tôi ngăn chặn các cảnh báo sau đó nó đánh bại mục đích.

Cảm ơn bạn đã bình luận của bạn, KSB

Trả lời

5

Điều này có thể sử dụng một phương pháp chung với một biến kiểu đệ quy. Hãy thử các cách sau:

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

Nên biên dịch tốt mà không có cảnh báo nào.

Tuy nhiên, nếu bạn có quyền kiểm soát bản đồ và có thể thay thế lớp của riêng bạn, có thể dễ đọc hơn để tạo nút lớp (trông giống như cây với tôi), chứa bản đồ thay thế. Một cái gì đó như:

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

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

Thay vào đó hãy Node làm đối số thứ hai thay thế. Chỉ là một gợi ý.

+0

waxwing thân yêu, Tôi đã kết thúc việc thực hiện đề xuất thứ hai của bạn bởi vì nó chỉ ra rằng tôi cần thêm những thứ bổ sung vào "nút" hơn là tham chiếu đến một hashmap khác. Nó cũng cảm thấy tự nhiên hơn nhiều. Tôi chỉ bắt tay với Java, vì vậy không thể hiểu đề xuất đầu tiên của bạn - phần "T mở rộng Bản đồ ". Cảm ơn bạn một lần nữa, KSB –

5

Bạn có thể sử dụng lớp này thay vì HashMap:

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

Kính gửi Hà, Không thực sự hiểu tại sao điều này có thể hoạt động (Java noob), do đó đã không dùng thử. Tôi sẽ đi với giải pháp Node của waxwing. Cảm ơn, KSB –

+0

Yeap, tạo lớp 'Node' (còn gọi là mẫu Composite) tốt hơn' HashMap'. –

1

Cấu trúc dữ liệu của bạn trông giống như bạn muốn đại diện cho các cây của tệp (tên tệp) với nó. Tôi không khuyên bạn nên làm điều này với HashMap như là loại nút.

tôi muốn đề nghị sử dụng Composite Pattern (xem wikipedia), mã đơn giản:

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 bạn đang sử dụng nắm để Set xuất hiện trong DirectoryNode.

+0

Cảm ơn bạn đã nghĩ. Các thực thể của tôi không thể được phân chia tự nhiên thành hai loại nút, tức là Thư mục và Tệp. Tất cả đều là "Tệp". Cụ thể, tôi cần phải thực hiện cùng một xử lý foo() ở tất cả các lớp của hệ thống phân cấp. Tôi không thể mở rộng mã của bạn để thực hiện việc này. –

+0

Tại sao không? Bạn có thể đặt tất cả mã bạn cần vào DirectoryNode.foo(). Bạn cũng có thể đặt mã vào Node.foo() và sau đó gọi super.foo() trên DirectoryNode.foo(). Sau đó, Node sẽ là tệp của bạn. – Wolfgang

+0

Tôi thấy những gì bạn đang nói: Đặt mã phổ biến bên trong Node (foo không trừu tượng nữa) và có File and Directory gọi super (filename). Sẽ nhớ điều đó. Xin cảm ơn, ksb –

Các vấn đề liên quan