Bimap —— 双向关联的数据结构
一、Bitmap 介绍
在 Java 集合类库中有个 Map,它的特点是存放的键(Key)是唯一的,而值(Value)可以不唯一,如果我们需要键(Key)和值(Value)都唯一,该怎么实现?这就是今天要谈的BiMap结构,它允许我们可以通过特定的 value 获取 key 值。
在过去,如果需要将Map结构中的键值对反转(也就是 key->value
转变成 value->key
),这时候我们需要定义两个Map数据结构来存储。但如果 Map 中存在多个 value 相同的元素会发生什么情况呢?这时候添加进去的 key 将会覆盖先前加进去的 key。如下所示:
k1->v1,k2->v2,k3->v3,k4->v1
如果我们需要反转 key 和 Value 将会变成 v1->k4,v2->k2,v3->k3
,这是因为Map的特点 v1->k4
将覆盖先前的 v1->k1
。
BiMap<K, V>
是 Map<K, V>
类型的数据类型(因为 BiMap 实现了 java.util.Map
接口,注意和 Multimap
的区别,Multimap 没实现 Map 接口)。
它的特点是它的 value 和它 key 一样也是不可重复的,换句话说它的 key 和 value 是等价的。如果你往 BiMap 的 value 里面放了重复的元素,就会得到 IllegalArgumentException
。
如下:
BiMap<String, String> upperToSmall = HashBiMap.create(); upperToSmall.put("A", "a"); upperToSmall.put("B", "b"); upperToSmall.put("C", "c"); // upperToSmall.put("D", "c"); System.out.println(upperToSmall.get("A"));
BiMap 强制其value的唯一性,如果发现违规则会抛出 IllegalArgumentException。
Exception in thread “main” java.lang.IllegalArgumentException: value already present: c at com.google.common.collect.HashBiMap.put(HashBiMap.java:241) at com.google.common.collect.HashBiMap.put(HashBiMap.java:218) at com.wyp.test.testFiles(test.java:142) at com.wyp.test.main(test.java:153)
那么,是不是当添加的value先前已经有了就不能添加了呢?答案是否,我们可以利用 BiMap 提供的 BiMap.forcePut(key, value)
来实现。那如何通过 BiMap 将 key和value 反转呢?很简单,代码如下:
BiMap<String, String> upperToSmall = HashBiMap.create(); upperToSmall.put("A", "a"); upperToSmall.put("B", "b"); upperToSmall.put("C", "c"); upperToSmall.forcePut("D","c"); System.out.println(upperToSmall.get("D")); // c BiMap<String, String> smallToUpper = upperToSmall.inverse(); System.out.println(smallToUpper.get("c")); // D smallToUpper.put("E","e"); System.out.println(upperToSmall); // {A=a, B=b, D=c, e=E} System.out.println(smallToUpper); // {a=A, b=B, c=D, E=e}
需要注意的是,inverse
方法返回一个反转后的 BiMap
,即 key/value 互相切换的映射。这个反转的 map 并不是一个新的 map(upperToSmall == upperToSmall.inverse().inverse()
),而是一个视图,这意味着,在这个反转后的map中的任何增删改操作都会影响原来的 map。
二、接口声明
以下是 com.google.common.collect.Bimap<K,V>
接口的声明:
@GwtCompatible public interface BiMap<K, V> extends Map<K, V> {
三、接口方法
官方文档:https://google.github.io/guava/releases/27.0.1-jre/api/docs/com/google/common/collect/BiMap.html
修饰符和类型 | 方法描述 |
---|---|
V | forcePut(K key, V value) 强制在BiMap中放入具有相同value值的键值对. |
BiMap<V,K> | inverse() 进行键值对的反转,返回BiMap的一种双向映射关系,所有对最初的BiMap的操作都会影响关联后的BiMap,同样的,对关联后BiMap的操作也影响最初的BiMap. |
V | put(K key, V value) 将指定的值与此映射中的指定键关联(可选操作). |
void | putAll(Map<? extends K,? extends V> map) 将指定映射中的所有映射复制到此映射(可选操作). |
Set<V> | values() 返回此映射中包含的值的Collection视图. |
从接口 java.util.Map
继承的方法
clear
compute
computeIfAbsent
computeIfPresent
containsKey
containsValue
entrySet
equals
forEach
get
getOrDefault
hashCode
isEmpty
keySet
merge
putIfAbsent
remove
replace
replaceAll
size
BiMap的常用实现有:
HashBiMap
:key 集合与 value 集合都有 HashMap 实现EnumBiMap
:key 与 value 都必须是 enum 类型ImmutableBiMap
:不可修改的 BiMap
四、测试类
package com.example.guava.collect; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import org.junit.Test; public class BimapTest{ @Test public void test1(){ BiMap<String, String> upperToSmall = HashBiMap.create(); upperToSmall.put("A", "a"); upperToSmall.put("B", "b"); upperToSmall.put("C", "c"); upperToSmall.forcePut("D","c"); System.out.println(upperToSmall.get("D")); // c BiMap<String, String> smallToUpper = upperToSmall.inverse(); System.out.println(smallToUpper.get("c")); // D smallToUpper.put("E","e"); System.out.println(upperToSmall); // {A=a, B=b, D=c, e=E} System.out.println(smallToUpper); // {a=A, b=B, c=D, E=e} } }
五、相关文章
未经允许请勿转载:程序喵 » Google Guava 快速入门 —— 【新集合】Bimap 类