Google Guava 快速入门 —— 【新集合】Bimap 类

Google Guava 快速入门.jpg

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

修饰符和类型方法描述
VforcePut(K key, V value) 
强制在BiMap中放入具有相同value值的键值对.
BiMap<V,K>inverse() 
进行键值对的反转,返回BiMap的一种双向映射关系,所有对最初的BiMap的操作都会影响关联后的BiMap,同样的,对关联后BiMap的操作也影响最初的BiMap.
Vput(K key, V value) 
将指定的值与此映射中的指定键关联(可选操作).
voidputAll(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 类

点  赞 (0) 打  赏
分享到: