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. day8 动态导入模块、socket进阶
  2. linux gcc 包含头文件 动态库 静态库 链接路径问题
  3. C++十进制数转换为二进制表示的算法(附完整源码)
  4. (三)ORB特征匹配
  5. 用GDI+转BMP为WMF、EXIF、EMF格式
  6. tar压缩/解压用法
  7. mobaxterm用alt键作为meta键的方法
  8. C 标准库—— stdlib.h(包括 rand srand 的实现)
  9. eclipse 无法启动选择的项,最近未进行任何启动
  10. linux 查看特定多个文件的总量
  11. 基于C语言图书馆管理系统编程设计
  12. Adobe Flash CS6 下载与安装教程
  13. Java实现冒泡排序(详解)
  14. cd linux 镜像,解开 CDLinux 的iso映像文件
  15. 基于Springboot实现英语在线学习系统
  16. 动态图解实例 ConstraintLayout Chain
  17. vue照片查看器插件v-viewer
  18. 掘金技术社区沸点指南(试行版)
  19. Spark 应用监控告警-Graphite_exporter
  20. 安卓:Day5 列表视图

热门文章

  1. ajax 泛微oa表单js_【泛微OA】付款报销单-检查部门是否填写以及调取明细表预算并计算差额...
  2. queen mary java_机器学习网站
  3. jar包执行命令脚本
  4. 项目开发中的一些注意事项以及技巧总结
  5. 使用RedisDesktopManager无法连接Redis服务器问题
  6. 东芝笔记本linux系统安装驱动,东芝笔记本自带蓝牙在Ubuntu中的驱动问题修复方法...
  7. Winbox v3使用介绍
  8. php 车牌号限号,车辆尾号限行API免费接口,车辆尾号限行API接口付费定制-进制数据...
  9. python模拟登录宁波大学邮箱
  10. 练手的PS作品(若侵删)