使用Google Guava来编写优雅的代码 – 集合4(BiMap)

BiMap提供了一种新的集合类型,它提供了key和value的双向关联的场景。

通常情况下,我们在使用Java的Map时,往往是通过key来查找value的,但是如果出现下面一种场景的情况,我们就需要额外编写一些代码了。

首先来看下面一种表示标识序号和文件名的map结构。

Map<String,String> logfileMap = Maps.newHashMap();
logfileMap.put("1","a.log");
logfileMap.put("2","b.log");
logfileMap.put("3","c.log");

当我们需要通过序号查找文件名,很简单。但是如果我们需要通过文件名查找其序号时,我们就不得不遍历map了。当然我们还可以编写一段Map倒转的方法来帮助实现倒置的映射关系。

// Generic method to reverse map.
public %lt;S,T> Map<T,S> getInverseMap(Map<S,T> map) {
    Map<T,S> inverseMap = new HashMap<T,S>();
    for(Entry<S,T> entry: map.entrySet()) {
        inverseMap.put(entry.getValue(), entry.getKey());
    }
    return inverseMap;
}

上面的代码可以帮助我们实现map倒转的要求,但是还有一些我们需要考虑的问题:

  1. 如何处理重复的value的情况。不考虑的话,反转的时候就会出现覆盖的情况.
  2. 如果在反转的map中增加一个新的key,倒转前的map是否需要更新一个值呢?

在这种情况下需要考虑的业务以外的内容就增加了,编写的代码也变得不那么易读了。这时我们就可以考虑使用Guava中的BiMap了。

使用BiMap

BiMap的使用也非常简单,可以先看下面一段简单示例:

BiMap<String,String> logfileMap = HashBiMap.create();

//像通常的Map那样初始化和使用
logfileMap.put("1","a.log");
logfileMap.put("2","b.log");
logfileMap.put("3","c.log");

System.out.println(logfileMap.get("1"));

BiMap<String,String> filelogMap = logfileMap.inverse();
System.out.println(filelogMap.get("c.log"));

看上去代码确实简洁了点,但是我们有些事情时需要注意的。

数据的强制唯一性

在使用BiMap时,会要求Value的唯一性。如果value重复了则会抛出现。

logfileMap.put("1","a.log");
logfileMap.put("2","a.log");//会抛出   IllegalArgumentException异常

但是如果你确实有可能会插入重复的value,那么你可以选择forcePut方法。当时需要需要注意的是前面的key也会被覆盖了。

logfileMap.put("1","a.log");
logfileMap.forcePut("2","a.log");
System.out.println(logfileMap.get("2"));//打印a.log
System.out.println(logfileMap.get("1"));//null

理解inverse方法

inverse方法会返回一个反转的BiMap,但是注意这个反转的map不是新的map对象,它实现了一种视图关联,这样你对于反转后的map的所有操作都会影响原先的map对象。

filelogMap.put("d.log","4");
System.out.println(logfileMap.get("4"));//打印d.log   

BiMap的实现类

BiMap提供了多种实现类,比如HashBiMap、ImmutableBiMap、EnumBiMap、EnumHashBiMap。

如果需要了解更多BiMap的内容可以前往查看以下资源