从Map <string,boolean =“”>将HashMap反转为Map <boolean,list <string =“”>&gt; </boolean,> </string,>

时间:2011-09-26 00:40:42

标签: java list dictionary arraylist hashmap

是否有更优雅/内置的方式来反转Hashmap的键和值?

我目前有以下内容。

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 个答案:

答案 0 :(得分:6)

您可以考虑使用Guava Multimap个实现之一。例如:

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

答案 1 :(得分:1)

我会做类似的事情(但如果你必须经常做这种事情,请考虑Guava),只用List替换List(看起来更加一致)并预先填充reversemap:

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

答案 2 :(得分:1)

首先要注意的是,如果您的值仅为真或假,则您不需要反向映射。如果你有更广泛的价值观,那将是有意义的。

获取具有特定值的条目的一种简单(但不是非常优雅)方式是:

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

如果你需要时不时地调用它,你可以看到这不太好。有两个不同的地图(直接和反向)并向两者添加条目是有意义的。您不能使用Bidi地图,因为键和值之间没有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));
  }
}

答案 3 :(得分:0)

GuavaBiMap已经提供了一种扭转其键值对的方法。也许您可以将相关Map的界面更改为BiMap,或者使用以下代码:

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