提升编程效率的利器: 解析Google Guava库之集合篇BitMap(三)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 提升编程效率的利器: 解析Google Guava库之集合篇BitMap(三)

Google Guava库提供了大量高效、有用的Java工具类,其中BiMap是一种非常独特的映射结构。与传统的Map不同,BiMap保证了键和值都是唯一的,因此它提供了键到值以及值到键的双向映射。这种数据结构在处理需要双向查找的场景时非常有用。


提升编程效率的利器: 解析Google Guava库之集合篇Immutable(一)

提升编程效率的利器: 解析Google Guava库之集合篇Multimap(二)

一、BiMap简介

BiMap,全称Bidirectional Map,即双向映射,是一种特殊的数据结构,它可以同时支持根据键查找值和根据值查找键的操作,这意味着在BiMap中,不仅键是唯一的,值也必须是唯一的。BiMap接口扩展了Map接口,并添加了一些方法来提供反向视图。

二、常用的BiMap实现类

Guava提供了HashBiMap和EnumBiMap两种常用的BiMap实现。

  • HashBiMap
    HashBiMap是基于哈希表的双向映射实现。它提供了常数时间的containsKey、get和put操作(假设哈希函数是完美的)。由于其基于哈希表,它不保证元素的顺序。
  • EnumBiMap
    EnumBiMap是一种特殊的BiMap,它要求键和值都是枚举类型。这种实现类型安全和高效,适用于键和值都是已知枚举值的情况。

三、BiMap的常用方法

除了继承自Map接口的方法外,BiMap还添加了一些特有的方法:

  • inverse(): 返回一个视图,其中的键和值与原BiMap中的值和键相反。注意,返回的是视图,对返回映射的更改将反映在原映射上,反之亦然。
  • forcePut(K key, V value): 类似于put方法,但如果键或值已经存在,则会抛出IllegalArgumentException。
  • containsValue(Object value): 检查BiMap中是否包含指定的值。

四、BIMap的用法

以下示例,展示了如何使用 Guava 的 HashBiMap 实现 BiMap 接口,并演示了它的多种方法:

import com.google.common.collect.BiMap;  
import com.google.common.collect.HashBiMap;  
  
import java.util.Set;  
  
public class BiMapExample {  
  
    public static void main(String[] args) {  
        // 创建一个空的HashBiMap  
        BiMap<String, Integer> biMap = HashBiMap.create();  
  
        // 向BiMap中添加元素  
        biMap.put("One", 1);  
        biMap.put("Two", 2);  
        biMap.put("Three", 3);  
  
        // 使用get方法通过键获取值  
        System.out.println("Two maps to: " + biMap.get("Two")); // 输出: Two maps to: 2  
  
        // 使用get方法通过值获取键(使用inverse()方法)  
        System.out.println("2 maps to: " + biMap.inverse().get(2)); // 输出: 2 maps to: Two  
  
        // 检查BiMap中是否包含某个键  
        System.out.println("Does the map contain key 'One'? " + biMap.containsKey("One")); // 输出: Does the map contain key 'One'? true  
  
        // 检查BiMap中是否包含某个值  
        System.out.println("Does the map contain value 2? " + biMap.containsValue(2)); // 输出: Does the map contain value 2? true  
  
        // 获取BiMap的键集  
        Set<String> keys = biMap.keySet();  
        System.out.println("Keys in the map: " + keys); // 输出: Keys in the map: [One, Two, Three]  
  
        // 获取BiMap的值集  
        Set<Integer> values = biMap.values();  
        System.out.println("Values in the map: " + values); // 输出: Values in the map: [1, 2, 3]  
  
        // 获取BiMap的大小  
        int size = biMap.size();  
        System.out.println("Size of the map: " + size); // 输出: Size of the map: 3  
  
        // 尝试添加一个已存在的键(这将抛出IllegalArgumentException)  
        try {  
            biMap.put("One", 4);  
        } catch (IllegalArgumentException e) {  
            System.out.println("Caught exception: " + e.getMessage()); // 输出: Caught exception: value already present: One  
        }  
  
        // 尝试添加一个已存在的值(这也将抛出IllegalArgumentException)  
        try {  
            biMap.put("Four", 1);  
        } catch (IllegalArgumentException e) {  
            System.out.println("Caught exception: " + e.getMessage()); // 输出: Caught exception: value already present: 1  
        }  
  
        // 使用forcePut方法替换现有键的值(不推荐,因为这会破坏BiMap的双向性)  
        // 注意:通常不建议使用forcePut,因为它可能会使BiMap处于不一致的状态  
        // biMap.forcePut("One", 4); // 这行代码被注释掉了,因为不推荐使用  
  
        // 从BiMap中移除一个键值对  
        Integer removedValue = biMap.remove("Two");  
        System.out.println("Removed value for key 'Two': " + removedValue); // 输出: Removed value for key 'Two': 2  
  
        // 清除整个BiMap  
        biMap.clear();  
        System.out.println("Is the map empty after clearing? " + biMap.isEmpty()); // 输出: Is the map empty after clearing? true  
    }  
}

注意:在这个例子中,没有使用 forcePut 方法,因为它会破坏 BiMap 的双向一致性。在实际开发中,你应该避免使用 forcePut 除非你非常清楚你在做什么,并且愿意接受可能带来的后果。

此外,由于 BiMap 保证键和值的唯一性,任何尝试插入重复键或值的操作都会抛出 IllegalArgumentException。这个特性使得 BiMap 特别适用于需要确保键值对唯一性的场景。

结论

BiMap是Guava库中一个非常有用的数据结构,它提供了双向映射的能力,同时保证了键和值的唯一性。在处理需要双向查找的场景时,使用BiMap可以简化代码并提高性能。HashBiMap和EnumBiMap是两种常见的实现,它们分别适用于不同的用例。通过inverse方法,我们可以轻松地获取反向视图,而不需要手动创建另一个映射。forcePut方法提供了一种在添加重复键或值时抛出异常的方式,这有助于在开发过程中及早发现问题。

相关文章
|
3月前
|
数据采集 JavaScript API
网页解析库:BeautifulSoup与Cheerio的选择
网页解析库:BeautifulSoup与Cheerio的选择
|
3月前
|
存储 Go PHP
Go语言中的加解密利器:go-crypto库全解析
在软件开发中,数据安全和隐私保护至关重要。`go-crypto` 是一个专为 Golang 设计的加密解密工具库,支持 AES 和 RSA 等加密算法,帮助开发者轻松实现数据的加密和解密,保障数据传输和存储的安全性。本文将详细介绍 `go-crypto` 的安装、特性及应用实例。
200 0
|
3月前
|
存储 Java 开发者
Java中的集合框架深入解析
【10月更文挑战第32天】本文旨在为读者揭开Java集合框架的神秘面纱,通过深入浅出的方式介绍其内部结构与运作机制。我们将从集合框架的设计哲学出发,探讨其如何影响我们的编程实践,并配以代码示例,展示如何在真实场景中应用这些知识。无论你是Java新手还是资深开发者,这篇文章都将为你提供新的视角和实用技巧。
48 0
|
4月前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
62 3
|
4月前
|
SQL Oracle 关系型数据库
SQL整库导出语录:全面解析与高效执行策略
在数据库管理和维护过程中,整库导出是一项常见的需求,无论是为了备份、迁移还是数据分析,掌握如何高效、准确地导出整个数据库至关重要
|
4月前
|
前端开发 JavaScript
pyquery:一个灵活方便的 HTML 解析库
pyquery:一个灵活方便的 HTML 解析库
43 1
|
5月前
|
缓存 网络协议 分布式数据库
超级好用的C++实用库之DNS解析
超级好用的C++实用库之DNS解析
110 0
|
5月前
|
XML JSON 网络协议
超级好用的C++实用库之字节流解析器
超级好用的C++实用库之字节流解析器
62 3
|
1月前
|
自然语言处理 数据处理 索引
mindspeed-llm源码解析(一)preprocess_data
mindspeed-llm是昇腾模型套件代码仓,原来叫"modelLink"。这篇文章带大家阅读一下数据处理脚本preprocess_data.py(基于1.0.0分支),数据处理是模型训练的第一步,经常会用到。
53 0
|
2月前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析

热门文章

最新文章

推荐镜像

更多