提升编程效率的利器: 解析Google Guava库之集合篇Table二维映射(四)

在Java开发中,我们经常使用Map数据结构来存储键值对,其中键是唯一的,可以快速查找到对应的值。但在某些场景下,我们可能需要一个更复杂的映射结构,其中键由两部分组成,类似于一个二维表格的行和列。Guava库中的Table接口正是为了满足这种需求而设计的。

一、什么是Guava Table?

Guava的Table是一种特殊的数据结构,它允许你使用两个键(通常被称为行键和列键)来映射一个值。你可以将Table视为一个二维的Map,其中每个单元格都由行键和列键唯一确定,并存储一个值。

二、Guava Table的实现类

Guava提供了几种Table的实现类,每种都有其特定的用途和性能特点:

  • HashBasedTable:这是最常用的实现,它基于哈希表来存储数据。HashBasedTable提供了快速的插入、查找和删除操作,并且不保证任何特定的键顺序。

  • TreeBasedTable:这个实现基于红黑树,它根据键的自然顺序或者提供的比较器对行键和列键进行排序。TreeBasedTable在按键顺序遍历数据时非常高效,但插入和查找操作可能比哈希表慢。

  • ImmutableTable:这是一个不可变的Table实现,它在创建时接收所有数据,并且之后不允许修改。ImmutableTable对于需要共享或发布不可变数据集的情况非常有用,同时它提供了高效的内存使用。

  • 除了上述标准实现外,你还可以通过实现Table接口来创建自定义的Table。这允许你根据特定需求定制存储和检索数据的方式。

三、如何使用Guava Table?

下面是一个Guava Table 使用示例,该示例将展示如何创建一个Table、向其添加数据、检索数据、修改数据、遍历数据,以及一些其他高级特性的使用。

import com.google.common.collect.HashBasedTable;  
import com.google.common.collect.Table;  import java.util.Map;  
import java.util.Set;  public class GuavaTableAdvancedExample {  public static void main(String[] args) {  // 创建一个Table实例  Table<String, String, Integer> workHoursTable = HashBasedTable.create();  // 添加数据  workHoursTable.put("Alice", "ProjectA", 40);  workHoursTable.put("Bob", "ProjectA", 30);  workHoursTable.put("Alice", "ProjectB", 20);  workHoursTable.put("Charlie", "ProjectC", 50);  // 检索数据  Integer aliceProjectAHours = workHoursTable.get("Alice", "ProjectA");  System.out.println("Alice worked " + aliceProjectAHours + " hours on ProjectA.");  // 使用row()方法获取特定行的映射  Map<String, Integer> aliceWorkHours = workHoursTable.row("Alice");  System.out.println("Alice's work hours: " + aliceWorkHours);  // 使用column()方法获取特定列的映射  Map<String, Integer> projectAWorkHours = workHoursTable.column("ProjectA");  System.out.println("Work hours on ProjectA: " + projectAWorkHours);  // 遍历表格  for (Table.Cell<String, String, Integer> cell : workHoursTable.cellSet()) {  System.out.println(cell.getRowKey() + " worked " + cell.getValue() + " hours on " + cell.getColumnKey() + ".");  }  // 修改数据  workHoursTable.put("Alice", "ProjectA", aliceProjectAHours + 5); // Alice在ProjectA上多工作了5小时  System.out.println("After update, Alice worked " + workHoursTable.get("Alice", "ProjectA") + " hours on ProjectA.");  // 检查是否包含某个键值对  boolean hasBobOnProjectB = workHoursTable.contains("Bob", "ProjectB");  System.out.println("Does Bob work on ProjectB? " + hasBobOnProjectB);  // 检查行键或列键是否存在  boolean hasRowKeyCharlie = workHoursTable.containsRow("Charlie");  boolean hasColumnKeyProjectD = workHoursTable.containsColumn("ProjectD");  System.out.println("Does the table have a row for Charlie? " + hasRowKeyCharlie);  System.out.println("Does the table have a column for ProjectD? " + hasColumnKeyProjectD);  // 获取所有的行键、列键或值  Set<String> allRowKeys = workHoursTable.rowKeySet();  Set<String> allColumnKeys = workHoursTable.columnKeySet();  Set<Integer> allValues = workHoursTable.values();  System.out.println("All row keys: " + allRowKeys);  System.out.println("All column keys: " + allColumnKeys);  System.out.println("All values: " + allValues);  // 移除数据  workHoursTable.remove("Alice", "ProjectB"); // Alice不再在ProjectB上工作  System.out.println("After removal, Alice's work hours on ProjectB: " + workHoursTable.get("Alice", "ProjectB"));  }  
}

在这个示例中,我们创建了一个HashBasedTable来存储员工在不同项目上的工作时间。我们展示了如何添加数据、检索特定员工在某个项目上的工作小时数、获取特定员工或特定项目的所有工作时间、遍历整个表格、修改数据、检查键的存在性、获取所有的键或值,以及移除数据。通过这个例子,你应该能够熟悉Guava Table的大部分常用方法。

如果你不使用table,那就需要用嵌套Map实现,代码可能就是下面这样

需要注意的是,与Guava Table相比,嵌套的Map在处理某些操作时可能会更加繁琐,例如检查列键是否存在,因为你需要遍历所有的内部Map。此外,嵌套的Map也没有Guava Table提供的一些高级功能和优化。

 // 创建一个嵌套的Map来模拟Table  Map<String, Map<String, Integer>> workHoursMap = new HashMap<>();  // 添加数据  addWorkHours(workHoursMap, "Alice", "ProjectA", 40);  addWorkHours(workHoursMap, "Bob", "ProjectA", 30);  addWorkHours(workHoursMap, "Alice", "ProjectB", 20);  addWorkHours(workHoursMap, "Charlie", "ProjectC", 50);  // 检索数据  Integer aliceProjectAHours = getWorkHours(workHoursMap, "Alice", "ProjectA");  System.out.println("Alice worked " + aliceProjectAHours + " hours on ProjectA.");  // 遍历嵌套Map  for (Map.Entry<String, Map<String, Integer>> entry : workHoursMap.entrySet()) {  String employee = entry.getKey();  Map<String, Integer> projects = entry.getValue();  for (Map.Entry<String, Integer> projectEntry : projects.entrySet()) {  String project = projectEntry.getKey();  Integer hours = projectEntry.getValue();  System.out.println(employee + " worked " + hours + " hours on " + project + ".");  }  }  // 修改数据  setWorkHours(workHoursMap, "Alice", "ProjectA", aliceProjectAHours + 5); // Alice在ProjectA上多工作了5小时  System.out.println("After update, Alice worked " + getWorkHours(workHoursMap, "Alice", "ProjectA") + " hours on ProjectA.");  // 检查是否包含某个键值对  boolean hasBobOnProjectB = containsWorkHours(workHoursMap, "Bob", "ProjectB");  System.out.println("Does Bob work on ProjectB? " + hasBobOnProjectB);  // 检查行键是否存在  boolean hasRowKeyCharlie = workHoursMap.containsKey("Charlie");  System.out.println("Does the nested map have an entry for Charlie? " + hasRowKeyCharlie);  // 检查列键是否存在(需要遍历所有内部Map)  boolean hasColumnKeyProjectD = false;  for (Map<String, Integer> projectMap : workHoursMap.values()) {  if (projectMap.containsKey("ProjectD")) {  hasColumnKeyProjectD = true;  break;  }  }  System.out.println("Does any employee work on ProjectD? " + hasColumnKeyProjectD);  // 移除数据  removeWorkHours(workHoursMap, "Alice", "ProjectB"); // Alice不再在ProjectB上工作  System.out.println("After removal, Alice's work hours on ProjectB: " + getWorkHours(workHoursMap, "Alice", "ProjectB"));  }  private static void addWorkHours(Map<String, Map<String, Integer>> workHoursMap, String rowKey, String columnKey, Integer value) {  workHoursMap.putIfAbsent(rowKey, new HashMap<>());  workHoursMap.get(rowKey).put(columnKey, value);  }  private static Integer getWorkHours(Map<String, Map<String, Integer>> workHoursMap, String rowKey, String columnKey) {  Map<String, Integer> projectMap = workHoursMap.get(rowKey);  return projectMap != null ? projectMap.get(columnKey) : null;  }  private static void setWorkHours(Map<String, Map<String, Integer>> workHoursMap, String rowKey, String columnKey, Integer value) {  workHoursMap.putIfAbsent(rowKey, new HashMap<>());  workHoursMap.get(rowKey).put(columnKey, value);  }  private static boolean containsWorkHours(Map<String, Map<String, Integer>> workHoursMap, String rowKey, String columnKey) {  Map<String, Integer> projectMap = workHoursMap.get(rowKey);  return projectMap != null && projectMap.containsKey(columnKey);  }  private static void removeWorkHours(Map<String, Map<String, Integer>> workHoursMap, String rowKey, String columnKey) {  Map<String, Integer> projectMap = workHoursMap.get(rowKey);  if (projectMap != null) {  projectMap.remove(columnKey);  if (projectMap.isEmpty()) {  workHoursMap.remove(rowKey);  }  }  }  

四、Guava Table的优势

使用Guava的Table而不是嵌套的Map有几个优势:

  • 类型安全:Table明确指定了行键、列键和值的类型,减少了类型转换的错误。
  • 更易用:Table提供了直观的API来插入、检索和遍历数据,使代码更易于阅读和维护。
  • 内存效率:Table实现类针对其特定用途进行了优化,以提供高效的内存使用。
  • 不变性:通过ImmutableTable,你可以创建不可变的表格,这对于并发编程和不可变对象模式非常有用。

五、总结

Guava的Table接口提供了一种强大且灵活的方式来处理需要使用两个键映射到一个值的情况。通过使用不同的实现类,你可以根据性能需求和特定场景选择最合适的Table。在需要处理二维数据或更复杂键结构的项目中,使用Guava的Table可以大大简化代码并提高开发效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/654223.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动化测试脚本编写(超详细)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 自动化测试脚本 什么是自动化测试&#xff1f; 自动化测试是验…

Spring Cloud + Vue前后端分离-第15章 课程总结

源代码在GitHub - 629y/course: Spring Cloud Vue前后端分离-在线课程 Spring Cloud Vue前后端分离-第15章 课程总结 重点难点梳理 环境的搭建 代码生成器 文件上传和视频播放 通用权限设计 学习技巧 养成做笔记的习惯 养成阶段性提交代码的习惯 问答区多交流

springboot 动态导出pdf

springboot 动态导出pdf 原理是通过freemarker插入数据到html模版里面&#xff0c;html你就叫前端帮你写好&#xff0c;他不写你就告诉你主管让他叫他写&#xff0c;你只管往预留的位置插入数据就行&#xff0c;然后通过itextpdf会将准备好html文件转成PDF。 ### 1、准备依赖 &…

思维题之T恤衫

[ABC332C] T-shirts - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 源于atcoder 由于字符串的长度为1000.不论怎样&#xff0c;顺序枚举即可。 import java.awt.FontFormatException; import java.awt.geom.AffineTransform; import java.awt.image.BandCombineOp; import …

自定义注解实现动态数据源

在Java开发中&#xff0c;使用多数据源能够提高系统的灵活性和性能。本文将通过介绍自定义注解的方式&#xff0c;实现动态数据源的切换。通过这种创新性的方法&#xff0c;开发者可以根据业务需求轻松切换数据库连接&#xff0c;实现数据源的动态管理&#xff0c;提升系统的可…

C++类和对象(中)

✨Blog&#xff1a;&#x1f970;不会敲代码的小张:)&#x1f970; &#x1f251;推荐专栏&#xff1a;C语言&#x1f92a;、Cpp&#x1f636;‍&#x1f32b;️、数据结构初阶&#x1f480; &#x1f4bd;座右铭&#xff1a;“記住&#xff0c;每一天都是一個新的開始&#x1…

如何在Win系统安装Jupyter Notbook并实现无公网ip远程访问本地笔记

文章目录 1.前言2.Jupyter Notebook的安装2.1 Jupyter Notebook下载安装2.2 Jupyter Notebook的配置2.3 Cpolar下载安装 3.Cpolar端口设置3.1 Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 在数据分析工作中&#xff0c;使用最多的无疑就是各种函数、图表、…

Mybatis-Plus基础

typora-copy-images-to: img Mybatis Plus 今日目标&#xff1a; 了解mybatisplus的特点能够掌握mybatisplus快速入门能够掌握mybatisplus常用注解能够掌握mybatisplus常用的增删改查能够掌握mybatisplus自动代码生成 1 MybatisPlus简介 1.1 MybatisPlus概述 ​ MyBatis-…

【前端web入门第二天】03 表单-下拉菜单 文本域 label标签 按钮 【附注册信息综合案例】

文章目录: 1. 下拉菜单 2. 文本域3.label标签 4.按钮- button 4.1 reset重置按钮结合form表单区域使用 5.无语义的布局标签 6.字符实体 注册信息综合案例 表单第二节 1. 下拉菜单 标签: select嵌套option,select是下拉菜单整体&#xff0c;option是下拉菜单的每一项。 代码…

MySQL运维实战(5.1) 字符和编码的基本概念

作者&#xff1a;俊达 字符和编码 字符 字符是符号&#xff0c;是人们用于交流的各类符号&#xff0c;如26个英文字母、汉字、标点符号、数学运算符、其他语言的字母和符号。 编码 编码是计算机中以二进制方式存储字符的方式。每个字符都有一个对应的编码值&#xff0c;计算机…

HarmonyOS --@state状态装饰器

在声明式UI中&#xff0c;是以状态驱动视图更新。 状态&#xff08;state&#xff09;&#xff1a;指驱动视图更新的数据&#xff08;被装饰器标记的变量&#xff09;。 试图&#xff08;view&#xff09;&#xff1a;基于UI描述渲染得到用户界面 State装饰器标记的变量必须初…

FPGA硬件架构

1.Xilinx FPGA是异构计算平台&#xff08;所谓异构&#xff0c;就是有很多不同的部分组成&#xff09;&#xff1a;CLB,BRAM,DSP 2. 软核&#xff1a; 把经过功能验证的、可综合的、实现后电路结构总门数在五千门以上的Verilog HDL模型称为软核(soft core)。 硬核: 把在某一…

数字化人才培养-流量的认知

1、流量的分类 公域/商域/私域 公域&#xff1a;公域流量指商家直接入驻平台实现流量转换&#xff0c;比如大家熟悉的拼多多、京东、淘宝、饿了么等&#xff0c;以及内容付费行业的喜马拉雅、知乎、得到等公域流量平台。 公域流量典型的代表有&#xff1a;抖音视频的曝光量、…

JavaScript DOM属性和方法之attribute属性对象

在HTML的DOM中&#xff0c;attribute对象表示HTML属性。HTML属性始终属于HTML元素&#xff0c;它在DOM节点中被称为属性节点。在DOM中&#xff0c;NamedNodeMap对象表示元素属性节点的无序集合&#xff0c;我们可以通过指定的索引访问指定的属性。通过element对象的attribute属…

小红树上染色

记忆化深搜 #include <iostream> #include <string> #include <stack> #include <vector> #include <queue> #include <deque> #include <set> #include <map> #include <unordered_map> #include <unordered_set&g…

JAVAEE初阶 网络编程(六)

TCP协议 一. 四次挥手二. 连接管理过程中TCP状态的变化2.1 listen状态2.2 established状态2.3 CLOSE_WAIT状态2.4 TIME_WAIT状态 三. 滑动窗口3.1 ack丢了3.2 数据丢了 一. 四次挥手 我们都知道&#xff0c;在三次握手中是可以把中间步骤合并成一个步骤执行&#xff0c;那么在四…

C语言数据结构(4)——线性表其三(双向链表)

欢迎来到博主的专栏——C语言数据结构 博主ID&#xff1a;代码小豪 文章目录 链表的种类头结点循环链表双向链表带头双向循环链表带头双向循环链表的定义与初始化 空链表尾插法打印双向链表头插法查找指定数据项的节点在指定位置之后插入节点指定位置的删除双向链表的销毁 顺序…

C语言第十二弹--扫雷

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 扫雷 1、扫雷游戏分析和设计 1.1、扫雷游戏的功能说明 1.2 游戏的分析和设计 1.2.1、数据结构的分析 1.2.2、文件结构设计 2、扫雷游戏的结构分析 2.1、用…

vmware虚拟机centos8共享文件夹挂载

1.设置虚拟机共享文件夹 2. 上述设置完毕之后&#xff0c;重启进入虚拟机&#xff0c;查看出现的共享文件夹名称 vmware-hgfsclient 3.查看是否有挂载目录&#xff0c;挂在目录默认为 /mnt/hgfs。没有时可以使用以下命令创建 mkdir /mnt/hgfs 4. 手动挂载目录--只能实现一次 注…

LarkXR引入2D共享模式,CloudXR新体验

Paraverse平行云自主研发的LarkXR&#xff0c;作为CloudXR解决方案的领军者&#xff0c;已在业界实现了显著的创新突破。LarkXR通过分钟级部署大规模云端资源、高度适配所有主流XR引擎&#xff0c;并灵活支持不同的交互和沉浸方式&#xff0c;成功地解决了Cloud XR商业化过程中…