Java中关于Map的理解

本文介绍了Java中Map接口及其主要实现类的特点与区别,包括HashMap、LinkedHashMap、TreeMap、Hashtable和Properties等。详细解析了HashMap的底层实现原理,从JDK 7到JDK 8的变化,以及其内部数据结构的调整。

Map(接口):存储k-v键值对双列数据。

主要实现类

HashMap:Map的主要实现类。线程不安全,效率高,可以存储null类型的key和value。

LinkedHashMap:HashMap的实现类。保证在遍历map时,可以按照添加元素的顺序进行遍历。

原因:在HashMap底层的基础上,添加了指针,一个指向前一个元素,一个指向后一个元素。对于频繁遍历的操作,效率高于HashMap。

TreeMap:按照添加的key-value进行排序,实现排序遍历。可以使用自然排序或则定制排序。底层使用的是红黑树。

Hashtable:Map的古老实现类。线t程安全的,但是效率t低。不可以存储null类型的key和value。

Properties:Hashtable的实现类。常用来处理配置文件,key和value都是String类型。

HashMap的底层

jdk 7及以前是数组+链表。

jdk 8 是数组+链表+红黑树。

Map中的结构

key:无序、不可重复的,使用Set存储所有的key。key所在的类要重写hashCode()和equals()方法

value:无序、可重复的,使用Collection存储所有的value。value所在的类要重写equals()方法。

key-value组成一个Entry对象。entry是无序的,不可重复的,使用Set存储所有的entry。

HashMap底层实现原理(jdk7)

HashMap map = new HashMap();

实例化HashMap的同时,底层创建一个长度为16的数组Entry[] table

map.put(key,value);

首先调用key所在类的hashCode()计算key的哈希值,此哈希值再经过某种算法之后,计算到的结果就是key在Entry[]数组中存放的位置;

  • 如果此位置上的数据为空,那么就直接添加;
  • 如果此位置上已有数据,那么比较key和已有数据(可能会有多个,以链表的形式存储)的哈希值,如果哈希值都不同,那么添加成功;如果哈希值也相同,那么调用key所在类的equals()方法。
  • 如果equals()方法返回false,则添加成功;如果返回true,则用value替换之前的值。

 在不断的添加过程中,如果要添加元素的长度大于临界值时,并且要添加的位置非空,那么就扩容。默认扩容为原来长度的2倍,并且将原有的数据都复制过来。

HashMap底层实现原理(jdk8)

  • HashMap map = new HashMap(); 实例化HashMap时,底层并没有创建长度为16的数组。
  • jdk8底层数组是Node[],而非Entry[]。
  • 首次调用put()时,底层创建长度为16的数组。
  • jdk7的底层是数组+链表;jdk8的底层是数组+链表+红黑树。
  • 当形成链表时,jdk7中是新的元素指向旧的元素。jdk8中是旧的元素指向新的元素。
  • 当数组某一索引位置上的元素以链表存储的长度>8且当前数组的长度>64时,索引位置上的数据使用红黑树存储。

HashMap源码关键参数:

  • DEFAULT_INITIAL_CAPACITY:HashMap默认容量,16。

  • DEFAULT_LOAD_FACTOR:HashMap的默认加载因子:0.75。

  • threshold:扩容临界值=默认容量*加载因子=12。

  • TREEIFY_THRESHOLD:链表长度大于该值,转化为红黑树:8。

  • MIN_TREEIFY_CAPACITY:Node被树化时最小hash表容量:64。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值