Reverse HashMap from map <String, Boolean> to map <Boolean, List <String>>

Is there a more elegant / built-in way to change Hashmap keys and values?

I currently have the following.

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; } 
+4
source share
4 answers

You can use one of Guava Multimap . For instance:

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

Or more generally:

 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; } 
+6
source

I would do something like this (but if you often do this so often, consider Guava), only replacing the List with Set (it seems a bit more consistent) and pre-populating the reverse map:

 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
source

First of all, it should be noted that you really do not need a reverse map if your values ​​are only true or false. This will make sense if you have a wider range of values.

One simple (but not very elegant) way to get records with a specific value:

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

You can see that this is not so good if you need to call him from time to time. It makes sense to have two different cards (straight and vice versa) and add entries to both. You cannot use Bidi cards, as there is no 1: 1 relationship between keys and values.

UPDATE: The following solution will not work. See Comments. You can also consider using TreeMap and keep it sorted based on value. This way you can have a sorted set by calling map.entrySet() at any time (first fails the records and then resolves). The disadvantage is that it is only one set.

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

+1
source

Guava BiMap already provides a method for changing its key-value pairs. Perhaps you can change the Map interface to a BiMap question, or use the following code:

 private BiMap<Boolean, String> reverseMap(Map<String, Boolean> permissions) { BiMap<String, Boolean> bimap = HashBiMap.create(permissions); return bimap.inverse(); } 
0
source

All Articles