BiMap提供了一种新的集合类型,它提供了key和value的双向关联的数据结构。
一般状况下,咱们在使用Java的Map时,每每是经过key来查找value的,可是若是出现下面一种场景的状况,咱们就须要额外编写一些代码了。首先来看下面一种表示标识序号和文件名的map结构。java
@Test public void logMapTest(){ Map<Integer,String> logfileMap = Maps.newHashMap(); logfileMap.put(1,"a.log"); logfileMap.put(2,"b.log"); logfileMap.put(3,"c.log"); System.out.println("logfileMap:"+logfileMap); }
当咱们须要经过序号查找文件名,很简单。可是若是咱们须要经过文件名查找其序号时,咱们就不得不遍历map了。固然咱们还能够编写一段Map倒转的方法来帮助实现倒置的映射关系。数据结构
/** * 逆转Map的key和value * @param <S> * @param <T> * @param map * @return */ public static <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; }
@Test public void logMapTest(){ Map<Integer,String> logfileMap = Maps.newHashMap(); logfileMap.put(1,"a.log"); logfileMap.put(2,"b.log"); logfileMap.put(3,"c.log"); System.out.println("logfileMap:"+logfileMap); Map<String,Integer> logfileInverseMap = Maps.newHashMap(); logfileInverseMap=getInverseMap(logfileMap); System.out.println("logfileInverseMap:"+logfileInverseMap); }
上面的代码能够帮助咱们实现map倒转的要求,可是还有一些咱们须要考虑的问题:
1. 如何处理重复的value的状况。不考虑的话,反转的时候就会出现覆盖的状况.
2. 若是在反转的map中增长一个新的key,倒转前的map是否须要更新一个值呢?
在这种状况下须要考虑的业务之外的内容就增长了,编写的代码也变得不那么易读了。这时咱们就能够考虑使用Guava中的BiMap了。spa
Bimap对象
Bimap使用很是的简单,对于上面的这种使用场景,咱们能够用很简单的代码就实现了:get
@Test public void BimapTest(){ BiMap<Integer,String> logfileMap = HashBiMap.create(); logfileMap.put(1,"a.log"); logfileMap.put(2,"b.log"); logfileMap.put(3,"c.log"); System.out.println("logfileMap:"+logfileMap); BiMap<String,Integer> filelogMap = logfileMap.inverse(); System.out.println("filelogMap:"+filelogMap); }
Bimap数据的强制惟一性io
在使用BiMap时,会要求Value的惟一性。若是value重复了则会抛出错误:java.lang.IllegalArgumentException,例如:file
@Test public void BimapTest(){ BiMap<Integer,String> logfileMap = HashBiMap.create(); logfileMap.put(1,"a.log"); logfileMap.put(2,"b.log"); logfileMap.put(3,"c.log"); logfileMap.put(4,"d.log"); logfileMap.put(5,"d.log"); }
logfileMap.put(5,"d.log") 会抛出java.lang.IllegalArgumentException: value already present: d.log的错误。若是咱们确实须要插入重复的value值,那能够选择forcePut方法。可是咱们须要注意的是前面的key也会被覆盖了。遍历
@Test public void BimapTest(){ BiMap<Integer,String> logfileMap = HashBiMap.create(); logfileMap.put(1,"a.log"); logfileMap.put(2,"b.log"); logfileMap.put(3,"c.log"); logfileMap.put(4,"d.log"); logfileMap.forcePut(5,"d.log"); System.out.println("logfileMap:"+logfileMap); } 输出: logfileMap:{5=d.log, 3=c.log, 2=b.log, 1=a.log}
理解inverse方法
inverse方法会返回一个反转的BiMap,可是注意这个反转的map不是新的map对象,它实现了一种视图关联,这样你对于反转后的map的全部操做都会影响原先的map对象。例如:map
@Test public void BimapTest(){ BiMap<Integer,String> logfileMap = HashBiMap.create(); logfileMap.put(1,"a.log"); logfileMap.put(2,"b.log"); logfileMap.put(3,"c.log"); System.out.println("logfileMap:"+logfileMap); BiMap<String,Integer> filelogMap = logfileMap.inverse(); System.out.println("filelogMap:"+filelogMap); logfileMap.put(4,"d.log"); System.out.println("logfileMap:"+logfileMap); System.out.println("filelogMap:"+filelogMap); }
输出:方法
logfileMap:{3=c.log, 2=b.log, 1=a.log} filelogMap:{c.log=3, b.log=2, a.log=1} logfileMap:{4=d.log, 3=c.log, 2=b.log, 1=a.log} filelogMap:{d.log=4, c.log=3, b.log=2, a.log=1}