HashMap和HashTable的区别


  1. 线程是否安全:HashMap 是非线程安全的,HashTable 是线程安全的;
  2. 效率:因为线程安全的问题,HashMap 要比 HashTable 效率高一点。另外,HashTable 基本被淘汰,不要在代码中使用它;(如果你要保证线程安全的话就使用 ConcurrentHashMap 吧!)
  3. 对Null key 和Null value的支持: HashMap 中,null 可以作为键,这样的键只有一个,可以有一个或多个键所对应的值为 null。。但是在 HashTable 中 put 进的键值只要有一个 null,直接抛出 NullPointerException。
  4. 初始容量大小和每次扩充容量大小的不同 :①创建时如果不指定容量初始值,Hashtable 默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。HashMap 默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。②创建时如果给定了容量初始值,那么 Hashtable 会直接使用你给定的大小,而 HashMap 会将其扩充为2的幂次方大小(HashMap 中的tableSizeFor()方法保证,下面给出了源代码)。也就是说 HashMap 总是使用2的幂作为哈希表的大小,后面会介绍到为什么是2的幂次方。
  5. 底层数据结构: JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。Hashtable 没有这样的机制。

HashMap相关


JDK1.7的HashMap的hash源码

static int hash(int h) {// This function ensures that hashCodes that differ only by// constant multiples at each bit position have a bounded// number of collisions (approximately 8 at default load factor).h ^= (h >>> 20) ^ (h >>> 12);return h ^ (h >>> 7) ^ (h >>> 4);
}

JDK 1.8 的 hash方法 相比于 JDK 1.7 hash 方法更加简化,但是原理不变。

static final int hash(Object key) {int h;// key.hashCode():返回散列值也就是hashcode// ^ :按位异或// >>>:无符号右移,忽略符号位,空位都以0补齐return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}

相比于 JDK1.8 的 hash 方法 ,JDK 1.7 的 hash 方法的性能会稍差一点点,因为毕竟扰动了 4 次。

相比于之前的版本, JDK1.8之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。

为什么HashMap的长度是2的幂次方


为了能让 HashMap 存取高效,尽量较少碰撞,也就是要尽量把数据分配均匀。我们上面也讲到了过了,Hash 值的范围值-2147483648到2147483647,前后加起来大概40亿的映射空间,只要哈希函数映射得比较均匀松散,一般应用是很难出现碰撞的。但问题是一个40亿长度的数组,内存是放不下的。所以这个散列值是不能直接拿来用的。用之前还要先做对数组的长度取模运算,得到的余数才能用来要存放的位置也就是对应的数组下标。这个数组下标的计算方法是“ (n - 1) & hash ”(等同于hash%length)。(n代表数组长度)。这也就解释了 HashMap 的长度为什么是2的幂次方。同时保证了下标不会超过数组的长度

下面这个方法保证了HashMap总是使用2的幂作为哈希表的大小

/*** Returns a power of two size for the given target capacity.*/static final int tableSizeFor(int cap) {int n = cap - 1;n |= n >>> 1;n |= n >>> 2;n |= n >>> 4;n |= n >>> 8;n |= n >>> 16;return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;}

ConcurrentHashMap 和 Hashtable 的区别


  • 底层数据结构: JDK1.7的 ConcurrentHashMap 底层采用 分段的数组+链表 实现,JDK1.8 采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树。Hashtable 和 JDK1.8 之前的 HashMap 的底层数据结构类似都是采用 数组+链表 的形式,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的;
  • 实现线程安全的方式(重要): ① 在JDK1.7的时候,ConcurrentHashMap(分段锁) 对整个桶数组进行了分割分段(Segment),每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。 到了 JDK1.8 的时候已经摒弃了Segment的概念,而是直接用 Node 数组+链表+红黑树的数据结构来实现,并发控制使用 synchronized 和 CAS 来操作。(JDK1.6以后 对 synchronized锁做了很多优化) 整个看起来就像是优化过且线程安全的 HashMap,虽然在JDK1.8中还能看到 Segment 的数据结构,但是已经简化了属性,只是为了兼容旧版本;② Hashtable(同一把锁) :使用 synchronized 来保证线程安全,效率非常低下。当一个线程访问同步方法时,其他线程也访问同步方法,可能会进入阻塞或轮询状态,如使用 put 添加元素,另一个线程不能使用 put 添加元素,也不能使用 get,竞争会越来越激烈效率越低。

咸鱼Java笔记:容器相关推荐

  1. 9.1-全栈Java笔记: 容器泛型—认识Collection接口

    开发和学习中需要时刻和数据打交道,如果组织这些数据是我们编程中重要的内容. 我们一般通过"容器"来容纳和管理数据.   事实上,数组就是一种容器,可以在其中放置对象或基本类型数据. ...

  2. Java 集合容器篇面试题(上)-王者笔记《收藏版》

    前期推荐阅读: Java基础知识学习总结(上) Java 基础知识学习总结(下) 大学生一个暑假学会5个神仙赚钱技能 | 你学会了几个? 毕设/私活/大佬必备,一个挣钱的开源前后端分离脚手架 目录 一 ...

  3. Java编程思想笔记——容器深入研究1

    完整的容器分类法 Java SE5新添加了: 1.Queue接口(LinkedList已经为实现该接口做了修改)及其实现PriorityQueue和各种风格的BlockingQueue. 2.Conc ...

  4. Java笔记05-Collection、泛型、迭代器

    Java笔记05-Collection.泛型.迭代器 [Collection.泛型] 主要内容 Collection集合 迭代器 增强for 泛型 第一章 Collection集合 1.1 集合概述 ...

  5. java笔记 方法_Java笔记-方法

    Java笔记-方法 1.何谓方法 2.方法的定义和调用 package src.method; import java.util.Scanner; public class Demo02 { publ ...

  6. 【Java笔记+踩坑】SpringBoot基础3——开发。热部署+配置高级+整合NoSQL/缓存/任务/邮件/监控

      导航: [黑马Java笔记+踩坑汇总]JavaSE+JavaWeb+SSM+SpringBoot+瑞吉外卖+SpringCloud/SpringCloudAlibaba+黑马旅游+谷粒商城 目录 ...

  7. GraalVM - 云原生时代的 Java 笔记

    GraalVM - 云原生时代的 Java 笔记 前言 GraalVM 诞生的背景 GraalVM Graal Compiler Benefits of JIT Creating a Native I ...

  8. 我的JAVA笔记之动态获取最近一年的月份(“yyyy-MM“)

    我的JAVA笔记之动态获取最近一年的月份 今天的日期是2020.7.4 打印格式如下: [2019-07, 2019-08, 2019-09, 2019-10, 2019-11, 2019-12, 2 ...

  9. java笔记(第一部分语法基础)

    java笔记 一. 计算机概述 1.1 计算机组成部分 1.2 人机交互方式 1.3 计算机语言 1.4 Java语言介绍 1.5 Java开发环境搭建 二.基本数据类型与运算 2.1 关键字 2.2 ...

最新文章

  1. 乱谈管理(优秀部门经理的职业素质)
  2. Reactjs 的 PropTypes 使用方法
  3. 微信小程序从oracle取数,微信小程序 取随机数
  4. C++中基于范围的for循环
  5. SCSS 文件里的感叹号用法 - 给变量设置默认值
  6. 装系统可能会出现的问题--无法装在该磁盘,因为格式的原因
  7. C++11 —— 基于区间(range)的 for 循环
  8. zedboard的DDR3型号MT41K128M16HA
  9. cocos2d-x 关于无法找到gl/gl.h头文件错误,以及r.java无法生成解决办法
  10. Scrapy 发起post请求
  11. 令牌环网概念_令牌环网工作原理_令牌环网为什么没人用
  12. 当BIM遇上GIS-无人机倾斜摄影三维建模(ContextCapture) 建设智慧城市方法详解
  13. android 照片 文件夹在哪里,Android手机照片文件夹在哪里?删除的手机照片怎么恢复...
  14. java程序员面试简历注意事项
  15. 一键构建云上高可用蛋白质结构预测平台
  16. 深度学习实战14(进阶版)-手写文字OCR识别,手写笔记也可以识别了
  17. 17.Unity3D商业游戏源码研究-变身吧主公-战斗-StateBase,PlayerBase
  18. 解决 用 Nginx 处理 跨域问题
  19. python k折交叉验证,python中sklearnk折交叉验证
  20. Windows10电脑用户中文名修改为英文名的详细教程【亲测有用】

热门文章

  1. ae合成设置快捷键_郑州UI设计学习进阶之AE导出GIF动画方法分享
  2. Csharp-堆栈基础
  3. ChatRoom新春版
  4. 【PS功能学习】09:合成——图层样式图层混合模式
  5. 微型计算机原理兰州大学出版社,10软件微机原理课设任务书.doc
  6. 【c++基础】第二章 微观部分:面向对象之类的组成
  7. 暴力破解密码(pywifi)python
  8. php正则匹配sg-nc-wap_Pandas基础操作(上)
  9. flash游戏引擎整理
  10. mysql触发器任务