关于Java两点须要更新的知识

HashMap的初始容量html

背景java

不少人能够把HashMap的原理描述的很溜。好比JDK1.7以前,底层数据结构是数组+链表。JDK1.8以后,出于效率上的考虑,在数组长度大于64,链表长度大于8的时候,会转换为红黑树。数据库

 

甚至知道对于赋值了容量的都会作一个变成2的n次方的操做。它的hash方法为了防止高位变化大或者低位变化大将它自己hash值右移16位和自身原hash值作一个按位异或操做再与容量-1作按位与。还知道默认的负载因子是0.75,这个值是通过几率论统计出来的,最好不要改。数组

 

了解的这么清楚,我就想问一下为何从数据库中取出来一个list,以后转换成hashmap。直接用的是Map map = new HashMap()或者是Map map = Maps.newHashMap(),为何不赋初始容量呢?数据结构

 

分析oracle

容量的大小会在put过程当中发生resize操做。若是初始不赋值。默认容量是16。那好比从数据库中取出来1000个元素。put过程当中会从16->32->64->128……,运行屡次resize操做。resize操做数组,须要将全部元素进行复制和rehash,效率是很低的。jvm

 

因此也有一些同窗考虑到这个问题,代码是这么写的: Map map = new HashMap(list.size());性能

 

这个写法也有问题,由于resize并非到达容量上限才resize。为了尽可能避免hash冲突,是超过阈值threshold就扩容。而这个threshold=容量*负载因子。3d

因此我更建议的写法是Map map = new HashMap(list.size()/负载因子)。htm

这样理论上能够比Map map = new HashMap(list.size())减小一次resize。

 

总结

在能够肯定HashMap容量时,最好Map map = new HashMap(list.size()/负载因子)来初始化,避免自动扩容带来的性能损耗。

 

思考

ConcurrentHashMap怎么来更合理的初始化?

 

JVM内存结构和Java内存模型

背景

前段时间偶然看到有篇文章批判不少人对「JVM内存模型」这个概念不清楚,说这个经典的图并非内存模型而是内存结构。

 

 

 

而内存模型应该是JSR133规范里介绍的volatile、final和synchronized等关键字的内存语义。

 

分析

这个很是富有淘金式思惟的做者却搞混了一个概念,看看下面JSR-133规范里是怎么说的:JSR133规范里讲的Java内存模型,并无说是JVM的内存模型啊。

Java内存模型讲的是Java语言自己的规范,这个规范包含了各个Java标准关键字在JVM里是怎样运做的。而JVM内存模型描述的是Java虚拟机怎样运行字节码的。因此上面经典的图说是JVM内存模型也不为过。不过根据官网,叫JVM内存结构更为标准。证据以下:

https://docs.oracle.com/javase/specs/jvms/se14/html/jvms-2.html#jvms-2.5 
在oracle官网里,介绍了这个概念

总结

Java内存模型和JVM内存模型是两个概念。

相关文章
相关标签/搜索