2015-10-01 51 views
2

我想爲不同類的對象編程一種註冊表。以類爲關鍵的TreeMap

我有以下幾點:

public interface DbObject{ 
    void setId(long id); 
    Long getId(); 
} 

實現此接口的原型類將是以下幾點:

public class BasicDbObject implements DbObject{ 
    private long id=null; 
    void setId(long id){ 
     this.id=id; 
    } 
    Long getId(){ 
     return id; 
    } 
} 

我想建立這個界面的各種不同的實現。 我希望能夠擁有一個Map對象,它可以從每個實現類映射到一個Map實例。

事情是這樣的:

Map <Class<C implements DbObject> , Map<Long, C>> registry = new TreeMap/HashMap/SomeOtherKindOfMap (...) 

我知道我可以做這樣的事情

Map <String,Map<Long,DbObjects>> registry = new ... 

但這種方式我會多寫一些代碼來確定名稱,比較類等。有沒有更簡單的方法來實現這一點?

所以我想知道的是:是否有可能將類對象作爲樹形圖中的鍵?

聲明一個映射對象的語法是什麼?映射從實現類C到映射對象從長對象(id)映射到C的實例?

我希望能夠做的請求如下所示:

BasicObject bo = registry.get(BasicObject.class).get(42); 

assuing ID以前那樣

BasicObject bo=new BasicObject(...); 
innerMap = new SomeMap<Long,BasicObject>(); 
innerMap.put(42,bo); 
registry.put(BasicObject.class,innerMap); 

請告訴我,如果這還不清楚,我很難解釋,因爲英語不是我的母語。

預先感謝您。


編輯:

事實證明,我可以做一些非常接近我想要的東西,周圍的地圖定義泛型類時:

public class ObjectRegistry <T extends DbObject>{ 

    private HashMap<Class<T>, TreeMap<Long,T>> registry=null; 

    ObjectRegistry(){ 
     registry=new HashMap<Class<T>, TreeMap<Long,T>>(); 
    } 
    public void register(T dbObject){ 
     TreeMap<Long, T> map = registry.get(dbObject.getClass()); 
     if (map==null){ 
      map=new TreeMap<Long,T>(); 
      registry.put((Class<T>) dbObject.getClass(),map); 
     } 
     map.put(dbObject.getId(),dbObject); 
    } 

    public <T extends DbObject>T get(Class<T> objectClass,long id){ 
     TreeMap<Long, T> map = (TreeMap<Long, T>) registry.get(objectClass); 
     if (map != null){ 
      return map.get(id); 
     } 
     return null; 
    } 

    public TreeMap<Long,T> getAll(Class<T> dbObjectClass) { 
     return registry.get(dbObjectClass); 
    } 
} 

我用一個TreeMap的內部映射,因爲我想輕鬆地返回按id排序的Class實例。

因此,精煉的問題是: 有沒有辦法做到這一點,沒有類頭的<T extends DbObject>子句?


編輯2:

通過它又在想,事實證明,約翰的回答是完全解決了這個。

這是我的最終代碼:

HashMap<Class<? extends DbObject>, TreeMap<Long, ? extends DbObject>> registry = null; 

public <T extends DbObject> T get(Class<T> clazz, long id) { 
    TreeMap<Long, T> map = (TreeMap<Long, T>) registry.get(clazz); 
    if (map != null) { 
     return map.get(id); 
    } 
    return null; 
} 

public <T extends DbObject> void register(T dbObject) { 
    TreeMap<Long, T> map = (TreeMap<Long, T>) registry.get(dbObject.getClass()); 
    if (map == null) { 
     map = new TreeMap<Long, T>(); 
     registry.put((Class<T>) dbObject.getClass(), map); 
    } 
    map.put(dbObject.getId(), dbObject); 
} 


public <T extends DbObject> TreeMap<Long, T> getAll(Class<T> dbObjectClass) { 
    return (TreeMap<Long, T>) registry.get(dbObjectClass); 
} 

它不需要在類頭<T extends DbObject>條款。

回答

3

所以我想知道的是:是否有可能將類對象作爲樹圖中的鍵?

TreeMap取決於是否有在鍵空間中的總順序,由具有天然順序(通過實施Comparable)鍵的類型所建立或者由單獨的Comparator對象,您提供。 Class es沒有自然順序。可以想象,你可以寫一個合適的Comparator,但是這對我來說似乎很有意思。

但是,爲什麼你特別需要一個TreeMap?您沒有描述任何其他種類的Map都沒有解決的要求。特別是,我幾乎總是發現HashMap是一個更好的選擇,我看不出有什麼理由不適合這個。它當然可以有Class類型的對象作爲鍵。此外,如果確實不需要任何特定的實施,那麼您最好是宣稱的類型只是簡單的Map。這樣,你可以實際上提供任何Map的實施,甚至改變你提供的一個,如果你發現這樣做的理由。

什麼將聲明一個地圖對象的語法中,從實現類C到地圖的地圖對象從長對象(ID)至C的實例每個映射?

您要求對每個值的類型的約束取決於相關鍵的類型,但是沒有辦法聲明強制這種關係的類型。 Map是否適合某個特定的鍵或特定的值是單獨映射的類型的函數,而不是其他類型的映射的函數。

您可以圍繞訪問您的地圖編寫泛型方法,它提供您所需的外觀,但是需要投射數據檢索方法。例如:

Map<Class<? extends DbObject>, Map<Long, ? extends DbObject>> registry = /*...*/; 

<T extends DbObject> Map<Long, T> getRegistryMap(Class<T> clazz) { 
    return (Map<Long, T>) registry.get(clazz); 
} 

<T extends DbObject> T get(Class<T> clazz, Long id) { 
    Map<Long, T> map = getRegistryMap(clazz); 

    return (map == null) ? null : map.get(id); 
} 

<T extends DbObject> T put(Class<T> clazz, Long id, T obj) { 
    Map<Long, T> map = getRegistryMap(clazz); 

    if (map == null) { 
     map = new HashMap<>(); 
     registry.put(clazz, map); 
    } 
    return map.put(id, obj); 
} 

更新補充:

所以精緻的問題是:有沒有辦法做到這一點,而不會在類頭<T extends DbObject>條款?

是的,我已經寫了。只要打一個簡單的類聲明就可以了。你不需要泛型類來擁有泛型方法。事實上,這兩者是正交的。 常規泛型類的方法可以使用該類的類型參數。這並不能使它們成爲通用的方法。如果方法聲明自己的類型參數,則方法是通用的,正如我在上面所做的那樣。你的get()方法也是這樣做的,重要的是要明白,你在方法簽名中明確聲明的類型參數<T>會隱藏類的同名類型參數:它是不同的T

+0

這不是關於樹圖,我可以使用其他類型的地圖,我知道。這是關於聲明地圖的語法。 –

+0

@StephanRichter,回答更新以解決您澄清的問題。 –

+0

好的,那基本上是我想知道的。我會讓它開放一些日子,也許有人有一個更好的想法/解決方法/無論。如果沒有,我會在接下來的日子裏將你的答案標記爲正確。謝謝,到目前爲止。 –