2011-09-26 55 views
4

是否有更優雅/內置的方式來反轉Hashmap的鍵和值?從地圖<String,布爾>逆轉HashMap到地圖<布爾,列表<String>>

我目前有以下幾種。

private Map<Boolean, List<String>> reverseMap(Map<String, Boolean> permissions) { 
    List<String> allow = new ArrayList<String>(); 
    List<String> deny = new ArrayList<String>(); 
    Map<Boolean, List<String>> returnvalue = new HashMap<Boolean, List<String>>(); 

    for (Entry<String, Boolean> entry : permissions.entrySet()) { 
     if(entry.getValue()) { 
      allow.add(entry.getKey()); 
     } else { 
      deny.add(entry.getKey()); 
     } 
    } 

    returnvalue.put(true, allow); 
    returnvalue.put(false, deny); 
    return returnvalue; 
} 
+5

你真的需要從布爾地圖嗎?只有兩個可能的鍵(true和false)。怎麼樣兩個集合,一個denyList和一個allowList? – Thilo

+0

@Thilo - 別忘了'null' :)但是,是的,我同意。 –

回答

6

您可以考慮使用GuavaMultimap實現之一。例如:

private Multimap<Boolean, String> reverseMap(Map<String, Boolean> permissions) { 
    Multimap<Boolean, String> multimap = ArrayListMultimap.create(); 
    for (Map.Entry<String, Boolean> entry : permissions.entrySet()) { 
     multimap.put(entry.getValue(), entry.getKey()); 
    } 
    return multimap; 
} 

或者更一般地說:

private static <K, V> Multimap<V, K> reverseMap(Map<K, V> source) { 
    Multimap<V, K> multimap = ArrayListMultimap.create(); 
    for (Map.Entry<K, V> entry : source.entrySet()) { 
     multimap.put(entry.getValue(), entry.getKey()); 
    } 
    return multimap; 
} 
+0

正是我在找的東西,謝謝:D – alexanderpas

1

我會做同樣的事情(但如果你必須經常做這樣的事情,考慮番石榴),只有設置更換名單(看起來更加一致)並預先填寫反向映射:

private Map<Boolean, Set<String>> reverseMap(Map<String, Boolean> permissions) { 
    Map<Boolean, Set<String>> returnvalue = new HashMap<Boolean, Set<String>>(); 
    returnvalue.put(Boolean.TRUE, new HashSet<String>()); 
    returnvalue.put(Boolean.FALSE, new HashSet<String>()); 
    for (Entry<String, Boolean> entry : permissions.entrySet()) 
     returnvalue.get(entry.getValue()).add(entry.getKey()); 
    return returnvalue; 
} 
1

首先要注意的是,如果您的值只有true或false,則您並不需要反向映射。如果你有更廣泛的價值觀,這將是有意義的。

一個簡單的(但不是很優雅)的方式與特定的值來得到的條目是:

public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) { 
    Set<T> keys = new HashSet<T>(); 
    for (Entry<T, E> entry : map.entrySet()) { 
     if (entry.getValue().equals(value)) { 
      keys.add(entry.getKey()); 
     } 
    } 
    return keys; 
} 

你可以看到,如果你需要不時地調用它每到這個也不是那麼好。有兩個不同的地圖(直線和反向)並向兩個地圖添加條目是有意義的。由於鍵和值之間不存在1:1關係,因此您無法使用雙向映射。

更新:以下解決方案不起作用。看評論。 你也可以考慮使用一個TreeMap,並根據這個值對它進行排序。通過這種方式,您可以隨時調用map.entrySet()進行排序(首先拒絕輸入,然後允許)。缺點是它只有一組。

ValueComparator bvc = new ValueComparator(map); 
TreeMap<String,Boolean> sorted_map = new TreeMap(bvc); 

class ValueComparator implements Comparator { 
    Map base; 

    public ValueComparator(Map base) { 
     this.base = base; 
    } 

    public int compare(Object a, Object b) { 
    return (Boolean)base.get(a).compareTo((Boolean)base.get(b)); 
    } 
} 

+0

我不認爲按照其他地圖中的值排序的'TreeMap'是個好主意 - 如果基本地圖的內容發生變化,那麼TreeMap中的樹會不一致,導致意想不到的結果。 –

+0

我的意思是使用TreeMap而不是最初的HashMap,對於混淆抱歉;-) – n0rm1e

+0

如果'base'是要插入的TreeMap,那麼當插入新事物(因爲'base。 get(newKey)'將爲空)。我不認爲你可以安全地保持一個TreeMap按值排序:( –

0

GuavaBiMap已經提供了用於反轉其鍵 - 值對的方法。也許你可以有問題的Map的接口更改爲BiMap,或者使用下面的代碼:

private BiMap<Boolean, String> reverseMap(Map<String, Boolean> permissions) { 
    BiMap<String, Boolean> bimap = HashBiMap.create(permissions); 
    return bimap.inverse(); 
} 
相關問題