Guava源码分析——Immutable Collections(4)

Immutable的集合体系,还有中很重要的集合没有介绍,就是ImmutableMap,通过UML图,可以看出ImmutableMap的结构体系。

首先来看一下ImmutableBiMap,因为普通ImmutableMap的实现依赖于它。ImmutableBiMap在ImmutableMap的基础上,加入inverse()等方法,可以使键值反转。ImmutableBiMap的构造,也是根据元素个数的不同,使用不同的实现(0-->EmptyImmutablBiMap,1-->SingletonImmutablBiMap,n(n>=2)-->RegularImmubtalMap),代码如下所示:

public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V> implements BiMap<K, V> {public static <K, V> ImmutableBiMap<K, V> of() {//Empty元素内部,不维护存储结构,inverse()方法直接返回thisreturn (ImmutableBiMap<K, V>) EmptyImmutableBiMap.INSTANCE;}public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) {//单个元素构造时,返回此类,内部维护两个元素K,V,inverse()时,返回V,K的SingletonImmutableBiMapreturn new SingletonImmutableBiMap<K, V>(k1, v1);}public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) {//多个元素构造是,返回此类,内部维护两个Entry[]集合,一个以key作为hashbucket的位置,
     //另一个以value作为hashbucket的位置,用于inverse()的时候,key-value的反转
return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2));} }

copyOf()方法,在ImmutableCollections中实现的原则就是,如果copyOf()的还是一份ImmutableCollections集合,那么只是进行引用的赋值,因为集合本身不可变。

看过ImmutableBiMap之后,在回头看ImmutableMap就简单了很多,只是在ImmutableBiMap基础上去除了inverse()方法,并在内部为户单一数组(hashbucket)

不需要维护反转的数组。在无元素和单一元素构造的时候,直接调用ImmutableBiMap.of()和ImmutableBiMap.of(K,V)方法,代码如下所示:

public abstract class ImmutableMap<K, V> implements Map<K, V>, Serializable {/*** Returns the empty map. This map behaves and performs comparably to* {@link Collections#emptyMap}, and is preferable mainly for consistency* and maintainability of your code.*/public static <K, V> ImmutableMap<K, V> of() {return ImmutableBiMap.of();}/*** Returns an immutable map containing a single entry. This map behaves and* performs comparably to {@link Collections#singletonMap} but will not accept* a null key or value. It is preferable mainly for consistency and* maintainability of your code.*/public static <K, V> ImmutableMap<K, V> of(K k1, V v1) {return ImmutableBiMap.of(k1, v1);}
}

多个元素构造的时候,返回RegularImmubtalMap,与RegularImmutableBiMap内部实现大同小异,去除对反转(值-键)的数组维护,去除inverse()等方法。

最后简单的阐述一下ImmutableSortedMap的实现,ImmutableMap单一元素和空元素的实现,就不详细说了,有兴趣的读者可以自己看看。多元素实现的时候,

ImmutableSortedMap的具体实现类是RegularImmutableSortedMap,有意思的是,它的内部维护key和value的数据结构是两个List,那么可想而知,排序早在构造的时候就已经完成了,而事实确实是这样,具体代码如下所示:

 @SuppressWarnings("unchecked")public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {//将排序器和entires传入fromEntries方法return fromEntries(Ordering.natural(), false, 4, entryOf(k1, v1), entryOf(k2, v2),entryOf(k3, v3), entryOf(k4, v4));}
  static <K, V> ImmutableSortedMap<K, V> fromEntries(Comparator<? super K> comparator, boolean sameComparator, int size, Entry<K, V>... entries) {for (int i = 0; i < size; i++) {Entry<K, V> entry = entries[i];entries[i] = entryOf(entry.getKey(), entry.getValue());}if (!sameComparator) {sortEntries(comparator, size, entries);//遍历entries排序
            validateEntries(size, entries, comparator);}return fromSortedEntries(comparator, size, entries);}
static <K, V> ImmutableSortedMap<K, V> fromSortedEntries( Comparator<? super K> comparator,int size,Entry<K, V>[] entries) {if (size == 0) {return emptyMap(comparator);}//遍历排序之后的entries,分开key和value,分别组成各自的ListImmutableList.Builder<K> keyBuilder = ImmutableList.builder();ImmutableList.Builder<V> valueBuilder = ImmutableList.builder();for (int i = 0; i < size; i++) {Entry<K, V> entry = entries[i];keyBuilder.add(entry.getKey());valueBuilder.add(entry.getValue());}return new RegularImmutableSortedMap<K, V>(new RegularImmutableSortedSet<K>(keyBuilder.build(), comparator),valueBuilder.build());
}

 ImmutableMap中的Entry,也是被Guava重新实现,增加了bucket的计算逻辑,如下图UML:

AbstractMapEntry在原有Map.entry基础上,将写操作,置为直接抛异常,ImmutableEntry实现getKey()和getValue(),ImmutableMapEntry再加入bucket的计算和维护方法(链表),最终反映到NonTerminalMapEntry和TerminalEntry,对于这两个类,TerminalEntry为bucket链表的尾结点,所以实现如下:

static final class TerminalEntry<K, V> extends ImmutableMapEntry<K, V> {TerminalEntry(ImmutableMapEntry<K, V> contents) {super(contents);}TerminalEntry(K key, V value) {super(key, value);}@Override@NullableImmutableMapEntry<K, V> getNextInKeyBucket() {//尾节点,所以没有nuextreturn null;}@Override@NullableImmutableMapEntry<K, V> getNextInValueBucket() {//尾节点,所以没有nuextreturn null;}}

而NonTerminalMapEntry的构造则需要传入下一个Entry

private static final class NonTerminalMapEntry<K, V> extends ImmutableMapEntry<K, V> {private final ImmutableMapEntry<K, V> nextInKeyBucket;NonTerminalMapEntry(K key, V value, ImmutableMapEntry<K, V> nextInKeyBucket) {super(key, value);this.nextInKeyBucket = nextInKeyBucket;}NonTerminalMapEntry(ImmutableMapEntry<K, V> contents, ImmutableMapEntry<K, V> nextInKeyBucket) {super(contents);this.nextInKeyBucket = nextInKeyBucket;}@OverrideImmutableMapEntry<K, V> getNextInKeyBucket() {//同一个bucket中的下一个Entryreturn nextInKeyBucket;}@Override@NullableImmutableMapEntry<K, V> getNextInValueBucket() {//BiMap才会维护Value的Bucketreturn null;}}

那么在构造的时候,如果产生hash冲突,就是用nonTerminalMapEntry,代码如下所示:

RegularImmutableMap(Entry<?, ?>[] theEntries) {int size = theEntries.length;entries = createEntryArray(size);int tableSize = Hashing.closedTableSize(size, MAX_LOAD_FACTOR);table = createEntryArray(tableSize);mask = tableSize - 1;for (int entryIndex = 0; entryIndex < size; entryIndex++) {@SuppressWarnings("unchecked") // all our callers carefully put in only Entry<K, V>sEntry<K, V> entry = (Entry<K, V>) theEntries[entryIndex];K key = entry.getKey();V value = entry.getValue();checkEntryNotNull(key, value);int tableIndex = Hashing.smear(key.hashCode()) & mask;@Nullable ImmutableMapEntry<K, V> existing = table[tableIndex];// prepend, not append, so the entries can be immutable//在构造是,如果产生hash冲突,那么直接的append到terminal的前面ImmutableMapEntry<K, V> newEntry = (existing == null)? new TerminalEntry<K, V>(key, value): new NonTerminalMapEntry<K, V>(key, value, existing);table[tableIndex] = newEntry;entries[entryIndex] = newEntry;checkNoConflictInBucket(key, newEntry, existing);}}

 

转载于:https://www.cnblogs.com/pona/p/4564256.html

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

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

相关文章

dual mysql 获取序列_MySQL获取周、月、天日期,生成排序号

常用MySQL生成时间序列--生成最近七天的日期&#xff0c;不包括当天SELECT cdate : date_add(cdate, interval - 1 day) as date FROM(SELECT cdate : date_add(date_sub(CURDATE(),interval 1 DAY), interval 1 DAY) from resource_publish) t0 LIMIT 7;2020-06-162020-06-15…

建筑电气工程设计常用图形和文字符号_怎么看懂建筑电气工程图?用最直白方式,教你基础识图!超级详细...

​如何看懂建筑电气工程图&#xff1f;我们可能知道AutoCAD&#xff0c;也可能知道在迅捷CAD图库下载建筑电气工程图纸&#xff0c;还可能会使用CAD绘制简单的图形对象。但是&#xff0c;当我们需要进行建筑识图的时候&#xff0c;你也可能连里面的经典图纸符号都不认识。如何看…

Android仿探探卡片拖拽,Vue 仿探探拖拽卡片的效果

原标题&#xff1a;Vue 仿探探拖拽卡片的效果已更新Vue3版&#xff0c;请给前端大全发送关键字vue3仿探探获取Vue3版类似 Tinder 和 探探 的卡片效果的组件&#xff0c;社区中已经非常多了。我这一版除了可以实现和他们一样的效果外。还增加了 飞卡 的效果&#xff0c;就是类似…

Codeforce 水题报告(2)

又水了一发Codeforce &#xff0c;这次继续发发题解顺便给自己PKUSC攒攒人品吧 CodeForces 438C&#xff1a;The Child and Polygon: 描述&#xff1a;给出一个多边形&#xff0c;求三角剖分的方案数&#xff08;n<200&#xff09;。 首先很明显可能是区间dp&#xff0c;我们…

itextpdf 怎么下划线_itext生成pdf设置下划线,itextpdf下划线,使用setUnderli

itext生成pdf设置下划线&#xff0c;itextpdf下划线,使用setUnderli使用setUnderline设置iText对象下划线显示我们可以使用setUnderline(float thickness, float yPosition)方法设置一个iText的Chunk对象下划线的显示样式。setUnderline方法的参数介绍&#xff1a;public Chunk…

textureview 旋转90度后平铺_C++初级编程NOIP题:11H1537: 图像旋转

时间限制: 1 Sec 内存限制: 128 MB题目描述输入一个n行m列的黑白图像&#xff0c;将它顺时针旋转90度后输出。输入第一行包含两个整数n和m&#xff0c;表示图像包含像素点的行数和列数。1 < n < 100&#xff0c;1 < m < 100。接下来n行&#xff0c;每行m个整数&…

android录音权限被占用,请问,app被用户禁止拍照和录音权限之后,拍照和录音事件应该怎么处理?...

另外android权限判断在6.0下没法直接判断然后通过代码设置&#xff0c;建议还是通过异常错误判断然后提示一下用户去手动修改权限。判断权限是否存在打开权限设置var r null;mui.plusReady(function () {document.querySelector(#btn1).addEventListener(tap,function () {r …

太阳粒子是什么东西_太阳粒子流是什么

匿名用户1级2011-06-21 回答因能量的增加而使得自身活动加强&#xff0c;从而向广袤的空间释放出大量带电粒子所形成的高速粒子流&#xff0c;科学家把这一现象比喻为太阳打“喷嚏”。由于太阳风中的气团主要内容是带电等离子体&#xff0c;并以每小时 150 万到 300 万公里的速…

qt中的qwidget如何实现自定义部件_2.3信号和槽(中)

2.3.1 在ui中编辑信号槽这一小节我们来看一下如何在ui中编辑信号槽。我们想要在ui中实现点击按钮&#xff0c;能够控制进度条的显隐。新建GUI项目SignalsAndSlots2&#xff0c;类名SignalsAndSlots2&#xff0c;基类选择QWidget。打开ui文件。在编辑界面中拖入一个Progress Bar…

html中 一条样式规则,css规则的基本格式是什么?

CSS(Cascading Styel Sheet)是控制 Web 页面外观的一系列格式设置规则,是网页设计必不可少的工具之一。下面我们就开始学习css的基本语法格式。css规则的基本格式是什么&#xff1f;层叠样式表是一个完全的纯文本文件&#xff0c;通常以“css”为扩展名作为单独的文件来使用…

css transtion不生效_CSS中transition属性不起作用的原因及解决方法

CSS中的transition属性可用于调整元素更改的时间&#xff0c;它可以像动画一样显示。虽然transition属性可以很方便的实现过渡效果&#xff0c;但是有时候可能会出现无效的情况&#xff0c;所以我们就需要来理解transition属性的写法规则。我们先来看一下CSS中transition属性不…

三白话经典算法系列 Shell排序实现

山是包插入的精髓排序排序&#xff0c;这种方法&#xff0c;也被称为窄增量排序。因为DL&#xff0e;Shell至1959提出命名。该方法的基本思想是&#xff1a;先将整个待排元素序列切割成若干个子序列&#xff08;由相隔某个“增量”的元素组成的&#xff09;分别进行直接插入排序…

python清空列表_Python之列表

Python变量没有数据类型&#xff0c;所以Python没有数组。整数&#xff1b;浮点数&#xff1b;字符串&#xff1b;对象创建一个列表&#xff1a;1.member[大鱼,123,3.14,[1,2,3]]2.empty[]向列表添加元素&#xff1a;append&#xff08;&#xff09;&#xff1a;member[大鱼,12…

java切面1.6需要的包_Java技术 AspectJ

AspectJ1 简介AspectJ&#xff1a;Java社区里最完整最流行的AOP框架。在Spring2.0以上版本中&#xff0c;可以使用基于AspectJ注解或基于XML配置的AOP。2 在Spring中启用AspectJ注解支持导入JAR包springsource.net.sf.cglib-2.2.0.jarspringsource.org.aopalliance-1.0.0.jarsp…

华为什么时候更新鸿蒙os,华为鸿蒙系统升级时间表

华为鸿蒙系统升级时间表6月2日HUAWEI Mate 40 ProHUAWEI P40 ProHUAWEI Mate 40 ProHUAWEI Mate 30 ProHUAWEI Mate 40 RS保时捷设计HUAWEI Mate 30 Pro 5GHUAWEI Mate 40HUAWEI Mate 30E Pro 5GHUAWEI Mate 40EHUAWEI Mate 30 RS保时捷设计HUAWEI Mate 2HUAWEI Mate 30HUAWEI …

vsftpd安装问题汇总(持续更新。。)

问题1. 在执行make命令时却出现了问题&#xff0c;具体如下&#xff1a; sysdeputil.o: In function vsf_sysdep_check_auth: sysdeputil.c:(.text0x109): undefined reference to crypt sysdeputil.c:(.text0x13a): undefined reference to crypt collect2: ld 返回 1 make: *…

python游戏程序编码_python实现的生成随机迷宫算法核心代码分享(含游戏完整代码)...

最近研究了下迷宫的生成算法&#xff0c;然后做了个简单的在线迷宫游戏。游戏地址和对应的开源项目地址可以通过上面的链接找到。开源项目中没有包含服务端的代码&#xff0c;因为服务端的代码实在太简单了。下面将简单的介绍下随机迷宫的生成算法。一旦理解后你会发现这个算法…

cesium等高线_Cesium专栏-气象站点色斑图、等值线图(不提供源码)

Cesium 是一款面向三维地球和地图的&#xff0c;世界级的JavaScript开源产品。它提供了基于JavaScript语言的开发包&#xff0c;方便用户快速搭建一款零插件的虚拟地球Web应用&#xff0c;并在性能&#xff0c;精度&#xff0c;渲染质量以及多平台&#xff0c;易用性上都有高质…

为什么OC语言很难

作为一个Objective-C的coder&#xff0c;我总能听到一部分人在这门语言上抱怨有很多问题。他们总在想快速学习这门语言来写一个App出来&#xff0c;但他们也总是联想到Objective-C看上去实在太难了或者在想这些语法符号都是神马玩意&#xff1f;不错&#xff0c;他们问得非常好…

小狐狸ChatGPT付费创作系统小程序端开发工具提示打开显示无法打开页面解决办法

最新版2.6.7版下载&#xff1a;https://download.csdn.net/download/mo3408/88656497 很多会员在上传小程序前端时经常出现首页无法打开的情况&#xff0c;错误提示无法打开该页面&#xff0c;不支持打开&#xff0c;这种问题其实就是权限问题&#xff0c;页面是通过调用web-v…