HashMap的初始容量

背景

很多人可以把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(),为什么不赋初始容量呢?

分析

容量的大小会在put过程中发生resize操作。如果初始不赋值。默认容量是16。那比如从数据库中取出来1000个元素。put过程中会从16->32->64->128……,运行多次resize操作。resize操作数组,需要将所有元素进行复制和rehash,效率是很低的。

所以也有一些同学考虑到这个问题,代码是这么写的: Map map = new HashMap(list.size());

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

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

这样理论上可以比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内存模型是两个概念。

关于Java两点需要更新的知识的更多相关文章

  1. Java 7 中的Switch 谈 Java版本更新和反编译知识

    Java 7 中的Switch 谈 Java版本更新和反编译知识          学习编程,享受生活,大家好,我是追寻梦的飞飞.今天主要讲述的是Java7中的更新Switch实现内部原理和JAD反编 ...

  2. Java并发编程学习前期知识下篇

    Java并发编程学习前期知识下篇 通过上一篇<Java并发编程学习前期知识上篇>我们知道了在Java并发中的可见性是什么?volatile的定义以及JMM的定义.我们先来看看几个大厂真实的 ...

  3. 《Java核心技术·卷Ⅰ:基础知识(原版10》学习笔记 第5章 继承

    <Java核心技术·卷Ⅰ:基础知识(原版10>学习笔记 第5章 继承 目录 <Java核心技术·卷Ⅰ:基础知识(原版10>学习笔记 第5章 继承 5.1 类.超类和子类 5.1 ...

  4. R.java不能自动更新

    1. The type R is already defined. (很多时候我们在导入其他人的程序的时候,会遇到这个错误) 通常在project里有两个R.java,一个在src,一个在gen,通常 ...

  5. Java批量插入更新操作

    以前总是说批量插入和更新的效率比非批量的要高,但是一直没有使用过批量处理数据的功能,现在由于项目中需要处理的数据量比较大,所以使用了批量处理的功能,java代码如下: 1.java实现批量插入数据: ...

  6. Java内存原型分析:基本知识

    转载: Java内存原型分析:基本知识 java虚拟机内存原型 寄存器:我们在程序中无法控制 栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中 堆:存放用new产生的数据 静 ...

  7. JAVA学习笔记—review基本知识[反射与异常]

    JAVA学习笔记—review基本知识[反射与异常] 1.异常: 1.1异常的分类: Java会将所有的异常封装成对象,其根本父类为Throwable. Throwable有两个子类:Error 和E ...

  8. Java 工程师应该掌握的知识

    以 Java 工程师应该掌握的知识为例,按重要程度排出六个梯度: 第一梯度:计算机组成原理.数据结构和算法.网络通信原理.操作系统原理. 第二梯度:Java 基础.JVM 内存模型和 GC 算法.JV ...

  9. Java全家桶的这些知识,不用学了

    众所周知,Java 的知识体系繁冗复杂,但是有很多知识在实际工作中几乎没有人用. 很多人在学习过程中,却经常把有限的时间和精力花在了这些"没有用"的知识上,事倍功半. 下面我捋一捋 ...

随机推荐

  1. Centos7 搭建bind9.9

    DNS服务器概述: DNS(Domain Name System),即域名系统. DNS服务器分为三种: 主域名服务器(Master Server).辅助域名服务器(Slave DNS).缓存服务器( ...

  2. JavaScript toFixed() 实现四舍五入保留两位小数

    const num = 18.186; let result; result = num.toFixed(2) console.log(result) // 18.19 注意,返回值为String类型

  3. libevent(八)激活事件

    激活事件添加流程 事件发生后,需要把对应的event加入到激活事件队列中. 整个流程如下: 对于定时器事件,在timeout_process过程中,会将事件从最小堆中删除. 激活事件处理流程 在eve ...

  4. Thinkphp 缓存RCE

     5.0.0<=ThinkPHP5<=5.0.10 .   漏洞利用条件: 1.基于tp5开发的代码中使用了Cache::set 进行缓存 2.在利用版本范围内 3.runtime目录可以 ...

  5. 基础JS遇到的一些题01

    1.两种数组去重方法 const unique = arr =>{ let mySet = new Set(arr); /!* let newArr =[]; for (let i = 0 ;i ...

  6. Coursera课程笔记----P4E.Capstone----Week 2&3

    Building a Search Engine(week 2&3) Search Engine Architecture Web Crawling Index Building Search ...

  7. 【FPGA篇章一】FPGA工作原理:详细介绍FPGA实现编程逻辑的机理

    欢迎大家关注我的微信公众账号,支持程序媛写出更多优秀的文章 FPGA(Field Programmable Gate Array),即现场可编程逻辑门阵列,它是作为专用集成电路(ASIC)领域中一种半 ...

  8. [hdu4598]二分图判定,差分约束

    题意: 给一个图,问能否给每个点分配一个实数值,使得存在一个数实数T,所有点满足:|value(i)| < T 且 u,v之间有边<=> |value(u)-value(v)| &g ...

  9. 瞬间教你学会使用java中list的retainAll方法

    retainAll方法简介 当我们有两个list集合的时候,我们可以使用retainAll方法求得两个list集合的子集.retainAll是Collection接口中提供的一个方法,各个实现类有自己 ...

  10. spring test---测试SpringMvc初识

    现在越来越多人使用SpringMvc来开发系统,在开发中可定需要对后台url地址请求测试,并且返回预期的结果! Spring提供的测试类MockMvc来进行url地址请求测试,使用方方式: packa ...