Java集合-Map八股文

本文介绍了Java中Map接口的基本概念及其主要实现类HashMap和TreeMap的特点。包括HashMap的工作原理、构造函数、扩容机制,以及TreeMap的排序方式和实现原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.Map

Map是Java集合相关的一个接口,主要是键值对的存储其元素需要重写hashCode()和equals()

Map的常用实现类有HashMap、HashTable、TreeMap

2.HashMap

HashMap和HashTable的元素无序、唯一,底层结构都是数组+链表

HashMap的key可以存入null,并且唯一;HashTable不允许key为null

HashMap线程不安全;HashTable是线程安全的

2.1.工作原理

  1. 首先通过hashCode()计算key的hash值,对数组长度取余得到存放数组的位置
  2. 遍历数组位置所在的链表,比较key是否相等,相等则替换value,返回原value
    • 比较hash值
    • 比较地址值
    • 调用equals()
  3. 判断是否需要扩容
  4. 在JDK1.7中采用头插法;在JDK1.8中采用尾插法,在链表的长度大于等于7时,如果数组长度 < 64,则进行扩容,否则进行树化

2.2.构造函数

JDK1.7

在JDK1.7中,使用无参构造时,默认数组长度为16,负载因子为0.75
然后调整数组长度为2的整数倍;确定数组扩容边界值:数组长度 * 负载因子

为什么数组长度必须是2的整数倍?

  1. 通过hash值对数组长度取余来确定数组位置时,使用了与运算&,效率比%更高;使用与运算的前提就是数组长度等于2的整数倍
    h & (length - 1) 等效于 h % length
  2. 减少哈希冲突

负载因子为什么是0.75

  1. 数组扩容边界值 = 数组长度 * 负载因子
  2. 如果设置为1:空间利用率高;但哈希碰撞的几率也变高,而链表的查询效率较低
  3. 如果设置为0.5:哈希碰撞的几率低,产生链表的几率低,查询效率高;但扩容频繁,空间利用率低
  4. 所以在 0.5 ~ 1 之间,取中间值:0.75

JDK1.8

在JDK1.8中,使用无参构造时,负载因子默认为0.75,其余属性都是默认值

2.3.扩容

在扩容时,扩容至原数组长度的2倍

3.TreeMap

TreeMap的元素唯一,升序排列;底层结构:红黑树

key必须实现比较器

  • 无参构造时,使用内部比较器:key实现Comparable接口;
  • 有参构造时,使用外部比较器:定义Comparator实现类

工作原理

  1. 第一次添加数据时,数据封装成新节点作为根节点root
  2. 第n次添加数据时,采用中序遍历,调用compare()比较key的大小,来选择合适的节点作为父节点;如果存在相等的key则替换并返回原value
  3. 为节点上色
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值