2012-04-10 34 views
5

Tôi đang tìm cách tạo HashMap ánh xạ tới các loại hỗn hợp.Lập bản đồ Java Các loại hỗn hợp

Ví dụ, sau đây sẽ làm việc trong Python (lưu ý rằng một Python dict là tương tự như một Java HashMap):

d = dict() 
d["str"] = "This is a string" 
d["flt"] = 1.23 
d["int"] = 5 

và khi truy cập vào d[x], loại thích hợp sẽ được trả lại (string, float, int trong ví dụ này).

Trong Java, tôi có thể đi với một HashMap<String, Object>, nhưng tôi không thực sự có một cách để ngay lập tức cho biết loại đối tượng là gì. Vì vậy, thay vào đó, tôi hiện đang cố gắng làm là tạo ra một lớp học MixedType chứa một đối tượng, nhưng cũng có thông tin kiểu gốc của nó, để tôi có thể downcast nó sau này. Ví dụ:

public class MixedMap 
    public static class MixedType 
    { 
     public Class<?> cls; 
     public Object val; 

     public MixedType(Class<?> c, Object v) 
     { 
      this.cls = c; 
      this.val = v; 
     } 
    } 

    public static void main(String args[]) 
    { 
     MixedType m1 = new MixedType(String.class, "This is a String"); 
     System.out.println((m1.cls)m1.val); 
    } 
} 

Lưu ý rằng đây là những gì tôi đang cố gắng làm :-) như nó hiện chưa được biên dịch phàn nàn rằng m1 cannot be resolved to a type.

Vì vậy, câu hỏi của tôi là, làm thế nào tôi có thể sửa lỗi này? Các cách khác để đạt được cùng một mục tiêu sẽ được hoan nghênh, nhưng xin đừng trả lời cho tôi biết rằng điều này hạn chế khả năng kiểm tra kiểu của trình biên dịch - tôi biết điều đó và OK với nó.

Xin cảm ơn trước.

+2

Tôi có thể hỏi: bạn sẽ làm gì với các đối tượng khi đã truy xuất? Tôi cảm thấy như thường có một cách tốt hơn để thiết kế này để tránh phải đúc ở tất cả. –

+1

Thậm chí nếu bạn có thông tin kiểu được lưu trữ trong các đối tượng 'đồng bằng' của mình, làm thế nào bạn có thể biết phải làm gì sau khi bạn truyền chúng? –

+0

Chắc chắn, tôi sẽ sử dụng HashMap làm đối tượng kiểu "cấu hình", trong đó người dùng sẽ chỉ định một số cài đặt cấu hình nhất định sẽ được phân tích cú pháp và đưa vào bản đồ này. Tại một số điểm nhất định trong chương trình, tôi sẽ kiểm tra xem có một tùy chọn cấu hình nào đó được thiết lập hay không, nếu sử dụng nó và nếu không sử dụng mặc định. Lý do cho nhu cầu về các loại hỗn hợp là một số tùy chọn cấu hình sẽ là chuỗi, một số tùy chọn khác sẽ xuất hiện, những thứ khác, v.v. – jedwards

Trả lời

6

Điều thích hợp cần làm là m1.cls.cast(m1.val), nhưng bạn gần như chắc chắn sẽ không đạt được bất kỳ thứ gì so với số đồng bằng Map<String, Object>. Một cách tiếp cận đơn giản hơn sẽ giúp bạn có được chính xác nhiều loại an toàn và chính xác cùng một thông tin - tức là, không nhiều - chỉ sử dụng phương pháp getClass() trên các giá trị Object trong bản đồ của bạn.

Không có điều nào trong số này sẽ hoàn thành mục tiêu của bạn là có thể nói String value = map.get("str") - không có gì ngắn của một diễn viên hoàn toàn sẽ làm điều đó. Bạn có thể làm

Object value = map.get("str"); 
if (value instanceof String) { 
    // do stringy things 
} 

hoặc điều gì đó dọc theo các dòng đó.

Nếu bạn biết các loại giá trị tại điểm sử dụng của chúng tại thời điểm biên dịch, thì đến nay giải pháp tốt nhất là chỉ cần tiếp tục và thực hiện các phôi tại các điểm sử dụng. Cách "lý tưởng" để làm cấu hình như thế này nói chung là không sử dụng Map, nhưng để xây dựng một lớp tùy chỉnh Configuration biết các trường và kiểu của nó tại thời gian biên dịch, nhưng nếu bạn muốn sử dụng Map, thì chỉ cần thực hiện phôi trực tiếp có lẽ là đặt cược tốt nhất của bạn.

+0

Cảm ơn bạn về nhiều giải pháp thay thế! – jedwards

1

Tôi đã triển khai một cái gì đó tương tự như trước đây. Bạn có thể sử dụng Generics để hỗ trợ. Những gì bạn muốn là một MixedKey, mà bạn có thể sử dụng như một chìa khóa vào một MixedMap. Một cái gì đó dọc theo các dòng này:

public class MixedKey<T> { 
    public final Class<T> cls; 
    public final String key; 

    public MixedKey(T cls, String key) { 
     this.key = key; 
     this.cls = cls; 
    } 

    // also implement equals and hashcode 
} 

.

public class MixedMap extends HashMap<MixedKey<?>,Object> { 
    public <T> T putMixed(MixedKey<T> key, T value) { 
     return key.cls.cast(put(key, value)); 
    } 

    public <T> T getMixed(MixedKey<T> key) { 
     return key.cls.cast(get(key)); 
    } 
} 

Những điều tốt đẹp về làm một cái gì đó như thế này là nó sẽ cung cấp cho bạn một lỗi thời gian biên dịch nếu bạn sử dụng các loại sai do nhầm lẫn, một cái gì đó bạn không nhận được với đúc trực tiếp:

MixedKey<Integer> keyForIntProperty 
    = new MixedKey<Integer>(Integer.class, "keyForIntProperty"); 

// ... 

String str = mixedMap.getMixed(keyForIntProperty); // compile-time error 

String str = (String)map.get("keyForIntProperty"); // run-time error only 
Các vấn đề liên quan