2014-01-23 31 views
1

我在我的應用程序中有兩個地圖,讓它成爲'用戶id'和'管理員id'。我使用它們通過其ID來獲得用戶:是否有可能在Java中有兩個其他地圖支持的Map?

Map<Id, Person> usersById = new HashMap<Id, Person>(); 
Map<Id, Person> managersById = new HashMap<Id, Person>(); 
Person me = usersById.get(myId); 

這兩個實體是人,所以有時我需要找到其ID的任意人。是的,我可以在一個地圖搜索,然後在另一個問題:

Person findArbitraryPerson(Id id) { 
    Person candidate = usersById.get(myId); 
    if (candidate == null) { 
     candidate = managersById.get(myId); 
    } 
    return candidate; 
} 

但是,可能有一個更好的辦法? 是的,我可以創建一個通用的人員地圖。但是我必須在每次到達時向該地圖添加一個新的Person實例,並將其刪除等。是否可以創建一種由「兩張地圖」支持的地圖,以便自動更新其內容?就像我可以在Collections框架中創建一個由原始地圖支持的子地圖一樣。

或者,可能有更好的解決方案?

+0

你是什麼意思「,但我必須在每次到達時向該地圖添加一個新的Person實例,並將其刪除等。「這裏有什麼意圖? – Sikorski

+1

爲什麼你首先有兩個hashmaps? –

+0

爲什麼你不能只使用用戶的地圖?經理沒有「用戶」ID? – Alessio

回答

1

這裏是一個只讀地圖(未經測試!),這是備份用任何數量的其他地圖:

private class ReadonlyProxyMap<K, V> implements Map<K, V> { 

     private final List<Map<K, V>> maps = new ArrayList<>(); 

     public void addMap(Map<K, V> map) { 
      maps.add(map); 
     } 

     @Override 
     public int size() { 
      return entrySet().size(); 
     } 

     @Override 
     public boolean isEmpty() { 
      for (Map<K, V> map : maps) { 
       if (!map.isEmpty()) { 
        return false; 
       } 
      } 
      return true; 
     } 

     @Override 
     public boolean containsKey(Object key) { 
      for (Map<K, V> map : maps) { 
       if (map.containsKey(key)) { 
        return true; 
       } 
      } 
      return false; 
     } 

     @Override 
     public boolean containsValue(Object value) { 
      for (Map<K, V> map : maps) { 
       if (map.containsValue(value)) { 
        return true; 
       } 
      } 
      return false; 
     } 

     @Override 
     public V get(Object key) { 
      for (Map<K, V> map : maps) { 
       if (map.containsKey(key)) { 
        return map.get(key); 
       } 
      } 
      return null; 
     } 

     @Override 
     public V put(K key, V value) { 
      throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 
     } 

     @Override 
     public V remove(Object key) { 
      throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 
     } 

     @Override 
     public void putAll(Map<? extends K, ? extends V> m) { 
      throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 
     } 

     @Override 
     public void clear() { 
      throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 
     } 

     @Override 
     public Set<K> keySet() { 
      Set<K> keySet = new HashSet<>(); 
      for (Map<K, V> map : maps) { 
       keySet.addAll(map.keySet()); 
      } 
      return keySet; 
     } 

     @Override 
     public Collection<V> values() { 
      List<V> values = new ArrayList<>(); 
      for (Map.Entry<K, V> entry : entrySet()) { 
       values.add(entry.getValue()); 
      } 
      return values; 
     } 

     @Override 
     public Set<Map.Entry<K, V>> entrySet() { 
      Set<K> keySet = new HashSet<>(); 
      Set<Map.Entry<K, V>> entrySet = new HashSet<>(); 
      for (Map<K, V> map : maps) { 
       for (Map.Entry<K, V> entry : map.entrySet()) { 
        if (!keySet.contains(entry.getKey())) { 
         entrySet.add(entry); 
         keySet.add(entry.getKey()); 
        } 
       } 
      } 
      return entrySet; 
     } 

    } 

然後你可以使用:

Map<Id, Person> usersById = new HashMap<>(); 
Map<Id, Person> managersById = new HashMap<>(); 
ReadonlyProxyMap<Id, Person> allPersons = new ReadonlyProxyMap<>(); 

... 

allPersons.addMap(usersById); 
allPersons.addMap(managersById); 

... 

Person findArbitraryPerson(Id id) { 
    return allPersons.get(myId); 
} 
+0

謝謝,普斯!看起來像我要求的解決方案..但不知道我想把這個巨大的代碼劃入我的項目。你有沒有在某些圖書館找到過這樣的東西? – KutaBeach

+0

Apache Commons Collections似乎有一個:http://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/map/CompositeMap.html – Puce

0

當然管理者也是人嗎?更好的方法是製作一張Person的地圖,並有Manager延伸Person

讓一個人查詢地圖並返回找到的Person。要讓管理員查詢地圖並檢查返回的對象是否爲Manager的實例,如果不是,則返回null。

我將整個HashMap包裝成一個類你自己的那類應該實現getPerson()getManager()getUser()適當的呼叫/檢查。這也將API從實現中分離出來,所以將來你可以隨時更改它,而不必更改任何其他代碼。

+0

>當然經理人也是人? - 我不確定,蒂姆:)我想保持分開遍歷經理和用戶列表的能力。 – KutaBeach

+0

@KutaBeach爲此,您需要一個自定義迭代器(即跳過錯誤類型的類型)或多個集合。 –

3

的擴展(和/或結論)我comment和@ BrianRoach的comment

public abstract class Person { 
    // general members and methods shared by managers and users 
} 

public class User extends Person { 
    // User specific members and methods 
} 

public class Manager extends Person { 
    // Manager specific members and methods 
} 

Map<Id,Person> map = new HashMap<Id, Person>(); 
map.put(new Id(), new Manager()); 
map.put(new Id(), new User()); 

或者(如果你是這樣的傾向),只是有Person對象上的布爾成員:isManager與適當的獲取/ setter方法。

+0

Benjamin,好主意,但我想爲用戶和管理者分配地圖,以便能夠遍歷所有管理者和用戶。是的,我也可以從頭開始,但是我必須每次都通過instanceOf檢查課程。 – KutaBeach

+0

爲什麼不只是布爾標誌isManager呢?你可以有一個人的地圖,只有你可以檢查他們是否是經理。 –

+0

當然,但這比遍歷拆分的用戶集合要長。事實上,我的問題是,是否有可能根據他們的身份單獨和統一訪問兩組項目。如果地圖支持兩個地圖不可用,看起來像我必須選擇你的解決方案.. – KutaBeach

相關問題