Map 在面试中永远是一个绕不开的点,本文将详细讲解Map的相关内容。关注公众号「Java面典」了解更多 Java 知识点。

Map

  • Map 是一个键值对(key-value)映射接口;
  • 映射中不能包含重复的键,每个键最多只能映射到一个值;
  • Map 允许以键集(keySet())、值集(valueSet())或键-值映射关系集(entrySet())的形式查看某个映射的内容。

HashMap

特点

  • 根据 key 的 hashCode 存储数据,大多数情况下(hash冲突时除外)可以直接定位到值;
  • HashMap具有较快的随机读取速度,遍历速度不可控;
  • 一个 HashMap 对象中最多只允许一条记录的键为 null,允许多条记录的值为 null;
  • HashMap是非线程安全的。

实现

可以看出 HashMap 其实是一个数组 + 单向链表组成。

容量

  • capacity:当前数组容量(默认16),始终保持 2^n,可以扩容,扩容后数组大小为当前的 2 倍;
  • loadFactor:负载因子,默认为 0.75;
  • threshold:扩容阈值,等于 capacity * loadFactor。

Java8实现

从 Java8 开始,Java 对 HashMap 的实现有了一定的改变,开始引入红黑树,所以其结构变成了 数组 + 链表 + 红黑树组成。

原因:当发生 hash 冲突时,在链表中查询 Node 的时间复杂度为 O(n),为了降低时间复杂度,引入红黑树,时间复杂度变为 O(logN)。

容量:除了Java7中的容量相关参数外,Java8为了引入红黑树,还引入了另外几个容量相关的变量。

  • static final int TREEIFY_THRESHOLD = 8:链表转树阈值。当链表长度 > 该值时,则将链表转换成红黑树;
  • static final int UNTREEIFY_THRESHOLD = 6:树还原链表阈值。当红黑树内节点数量 < 6时,则将红黑树转换成链表;
  • static final int MIN_TREEIFY_CAPACITY = 64:最小树化阈值。当哈希表中的容量 > 该值时,才允许链表转化为红黑树。否则将直接扩容。为了避免进行扩容、树形化选择的冲突,这个值不能小于 4 * TREEIFY_THRESHOLD。

ConcurrentHashMap

特点

  • ConcurrentHashMap 其实就是一个线程安全的HashMap;
  • ConcurrentHashMap key 和 value 均不允许为 null。

网上关于key 和 value 不允许为 null 的解释是这样描述的:如果map.get(key)return null,则无法检测到该键是否显式映射到 null 该键。在非并行映射中,您可以通过进行检查 map.contains(key),但在并行映射中,两次调用之间的映射可能已更改

实现

[ConcurrentHashMap.png]

  • ConcurreuntHashMap 实现和 HashMap 差不多的,但是为了支持并发操作,引入了 Segment,ConcurreuntHashMap 由一个 Segment 数组组成;
  • Segment 通过继承 ReentrantLock 来进行加锁,Segment 数组就相当于是 ConcurreuntHashMap 的分段锁,每次操作只用锁住对应的 Segment 就行了;
  • Segment 内部由 HashMap 组成;
  • concurrencyLevel:并行级别,默认16。其实就是 ConcurreuntHashMap 由长度为 16 的 Segment 组成,所以可以理解为 ConcurreuntHashMap 默认同时可以支持最多 16 个线程并发写。Segment 数组可以在初始化的时候指定,初始化后不可扩容。

Java8实现

和 HashMap 一样, ConcurrentHashMap 在 Java8 中也引入了红黑树的机制。在这里就不再赘述了。

LinkedHashMap

LinkedHashMap 是 HashMap 的一个子类,它记录了元素插入的顺序,能够保证在使用迭代器遍历的时候,先插入的元素先获取。也可在构造时带参数,按照访问次序排序。

WeakHashMap

特点

  • WeakHashMap 键值都可以是null;
  • WeakHashMap 的键是“弱键”。当某个键不再正常使用时,会被从 WeakHashMap 中被自动移除。

弱键原理

  • 弱键通过 WeakReference 和 ReferenceQueue 实现,
  • WeakHashMap 的 key 是 WeakReference 类型的, ReferenceQueue是一个队列,它会保存被GC回收的“弱键”;
  • 当某“弱键”不再被其它对象引用,并被GC回收时,这个“弱键”也同时会被添加到 ReferenceQueue(queue) 队列中;
  • 当再次操作 WeakHashMap 时,会先同步 table 和 queue 。table 中保存了全部的键值对,而 queue 中保存被 GC 回收的键值对;同步它们,就是删除 table 中被 GC 回收的键值对。

主要变量

  • table:是一个Entry[]数组类型,用于存储键值对;
  • size: 表示 WeakHashMap 的大小;
  • threshold :阈值,用于判断是否需要调整容量,threshold的值="容量*加载因子";
  • loadFactor: 加载因子;
  • modCount:是用来实现fail-fast机制的
  • queue:保存的是“已被GC清除”的“弱引用的键”。

TreeMap

  • TreeMap 实现 SortedMap 接口,能够把它保存的记录根据键排序;
  • 默认按照键值升序排序,也可指定排序的比较器;
  • 在使用 TreeMap 时,key 必须实现 Comparable 接口或者在构造 TreeMap 传入自定义的 Comparator,否则会在运行时抛出 java.lang.ClassCastException 类型的异常。

Hashtable

  • Hashtable 继承自 Dictionary 接口,相当于介于 HashMap 与 ConcurrentHashMap 之间的一种哈希表;
  • 相较于 HashMap 而言,他是线程安全的,同时与 ConcurrentHashMap 一样,key vlaue 均不能为null;
  • 相较于 ConcurrentHashMap 而言,Hashtable 不支持多线程同时操作。
  • 所以在在单线程环境一般使用 HashMap,而在多线程环境中,使用 ConcurrentHashMap 。

Java集合系列推荐

Java集合02——三分钟了解你必须掌握的两个Set

Java集合01——List 的几个实现类,了解一下?

Java集合03——你不得不了解的Map的更多相关文章

  1. Java集合的Stack、Queue、Map的遍历

    Java集合的Stack.Queue.Map的遍历   在集合操作中,常常离不开对集合的遍历,对集合遍历一般来说一个foreach就搞定了,但是,对于Stack.Queue.Map类型的遍历,还是有一 ...

  2. Java集合:List、Set和Map的区别,ArrayList和LinkedList有何区别..........

    一.数组和集合的区别: 数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型): 集合可以存储和操作数目不固定的一组数据. 所有的JAVA集合都位于 java.util包中! J ...

  3. Java集合中List、Set以及Map

    概述: List , Set, Map都是接口:List , Set继承至Collection接口,Map为独立接口 Set下有HashSet,LinkedHashSet,TreeSet List下有 ...

  4. Java 集合(List、Set、Map 等)相关问答归纳再整理

    写在最前面 这个项目是从20年末就立好的 flag,经过几年的学习,回过头再去看很多知识点又有新的理解.所以趁着找实习的准备,结合以前的学习储备,创建一个主要针对应届生和初学者的 Java 开源知识项 ...

  5. java集合框架--List、Set、Map

      1.List:有序的 collection(也称为序列).此接口可以对列表中每个元素的插入位置进行精确地控制.可以根据元素的在列表中的位置访问元素,并搜索列表中的元素.列表允许重复的元素.    ...

  6. java集合: List、Set、Map总结 + HashMap/Hashtable 差别

    List:(有序,能够反复)通过下标索引     ----ArrayList  可变数组,随机查找     ----LinkedList    链表,不论什么位置插入删除快     ----Vecto ...

  7. java集合框架复习----(4)Map、List、set

    文章目录 五.Map集合[重要] 1.hashMap 六.Collections工具类 总结 集合的概念 List集合 set集合: Map集合 Collection 五.Map集合[重要] 特点: ...

  8. java 集合(list、set、map)的特点

    集合相关的类有一大堆,一般也只用到常用的方法增删改查,而且它它们的方法名也基本一样,所以一直都不知道什么时候用什么集合, 今天趁有空特意从网上整理资料方便日后回忆. 一.List:.有顺序以线性方式存 ...

  9. Java集合总结(二):Map和Set

    集合类的架构图: HashMap 内部维护一个链表数组做哈希表,默认大小为16,最大值可以为2^30,默认负载因子0.75. 可以通过构造方法指定初始大小和负载因子,当键值对个数大于等于临界值thre ...

随机推荐

  1. 函数动态参数和Python中的三种空间

    动态参数 : *args 实参角度: 定义一个函数时, * 将所有的位置参数聚合到一个元祖中 顺序 : 位置参数 > * args > 默认参数 > **kwargs 接受所有参数 ...

  2. maxquant|

    使用maxquant 设定修饰: 设定打分值: 设定有标定量方法:iBAQ,虽然是无标定量方法,但是设定该值后也会有相应有标定量方法的iBAQ值. 根据计算机性能设定线程数: 设定酶切位点 最后生成文 ...

  3. Windows 10操作系统针对不同环境下的安装方法

    一.电脑系统能正常运行 1.解压win10镜像文件 到电脑的非系统分区,运行setup安装文件 2.点击setup应用程序,准备安装 3.准备安装 4.等待安装过程结束,重启即可. 二.光盘安装 1. ...

  4. [LC] 7. Reverse Integer

    Given a 32-bit signed integer, reverse digits of an integer. Example 1: Input: 123 Output: 321 Examp ...

  5. 快速搭建本地Nuget服务

    一  创建Nuget 服务项目 1.创建一个空白的asp.net web项目,需要.net 4.6以上 2.在Nuget中搜索 nuget.server ,可以看到是由 .Net 基金再维护的,几乎傻 ...

  6. scarky test

  7. 基于Jquery的textarea滚动条插件(原创)

    之前项目中自己写的滚动条插件.先前太忙没有好好整理.现在项目间歇期拿出来整理后贴出来 Demo Here css 我是把mCustomScrollbar 的UI 扣下来的. 这里我要介绍下这个插件不错 ...

  8. vue2.0一个弹窗组件

  9. Spring Boot 鉴权之—— springboot2.0.4+mybatis 整合的完整用例

    自上一篇文章的基础上,Spring Boot 鉴权之—— JWT 鉴权我做了一波springboot2.0.4+mybatis 的整合. 参考文章: Spring Boot+Spring Securi ...

  10. Python测试开发-创建模态框及保存数据

    Python测试开发-创建模态框及保存数据 原创: fin  测试开发社区  前天 什么是模态框? 模态框是指的在覆盖在父窗体上的子窗体.可用来做交互,我们经常会看到模态框用来登录.确定等等,到底是怎 ...