接口Map的方法介绍及其底层的实现
一、方法 Map是一个键值对结构的数据类型
key:我们要通过key去找我们对应的值
value:我们存放的具体信息
我们存储的信息都是以key作为标识,所以key不能重复
如果key信息重复,后面会把前面的给覆盖掉
增:put ( K key , V value ) :添加一个元素进入Map类对象末尾;因为元素的关键字是唯一的,当使用put方法的时候,该方法会将所添加元素,按照他所对应的关键字,添加到对应关键字位置,并覆盖原有权值,这时候,put方法就会把原有的对应该关键字的权值返回回来。
【接口Map的方法介绍及其底层的实现】putAll ( Maps < ? extends K , ?extends V > m) :将另一个Map类型对象添加至调用他的对象的末尾;
删:clear ( ) :清空调用该函数的Map类对象;
remove ( Object k ) :移除关键字为k的元素;
改:put即可实现;
查:get ( Object k ) :获取对应关键字为k值的元素;这里需要注意一点的是,我们可以通过个get方法来判断对应的Map类对象是否存在,当然,这种判断方法用在对应的Hashtable类当中是最合适的,因为该类不会出现赋值为空的情况。但是,这并不表示着这种判断存在的方法只能用在Hashtable类中,在大多数情况下,我们都是将这种方法放在HashMap类中使用的,因为,实际上赋值为空的情况是没有意义的一般很少出现
size ( ) :获取调用该函数的Map类对象的大小;
value ( ) :返回调用他的Map类对象关于其中元素权值的一个Collection类对象,这个函数的作用就是为了拿值;
set
set
判断:containValue ( Object v ) :判断调用该函数的类中是否有权值为v的元素;
containKey ( Object k ) :判断调用该函数的类中是否有关键字为k的元素;
isEmpty ( ) :继承自Object的通用方法。
这里面我们需要强调的是两个方法,一个是entrySet,另一个是keySet。
二、底层实现 /**
* Map
*
创建对象
*
//默认的初始容量16
*
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
*
//默认的使用的大小是总大小的75%
*
static final float DEFAULT_LOAD_FACTOR = 0.75f;
*
//map中数组可用的大小
*
int threshold;
*
//map中数组存放数据大小
*
int size;
*
//创建对象的时候默认创建一个空的entry数组
*
transient Entry[] table = (Entry[]) EMPTY_TABLE;
*
存放数据
*
第一次存放数据
*
首先检查数组是不是默认的,如果是第一次需要创建一个新的
*
新创建的数组是entry类型的,大小为16,可用为12
*
计算key的hash值,相对是唯一的
*
然后根据数组的大小计算当前key所应该处于的索引位置
*
然后创建新的entry将数据存放至数组
*
第一次之后加入数据
*
首先计算key对应的hash值,算出对应的位置索引
*
判断当前key有没有指定值,
*
如果已经存在值
*
就会把原来的值返回,并且新的value覆盖掉原来的值
*
如果已经不存在值
*
我们还需要判断当前数组容量是否足够
*
扩容大小为原来的两倍,可用的大小也为原来的两倍,总大小的0.75
*
最后将其存放至容器
*
取出数据
*
首先判断map是否为空,为空直接null
*
不为空,计算当前key的hash值,然后计算索引值
*
取出map的数组中指定位置的entry,然后进行比较
*
比较当前对象,如果当前对象不equals,开始比较单向链表中的entry
*
比较的时候先比较hash && 如果hash都不一样,对象肯定不一样,提高效率
*
* 为什么map数组的大小只允许使用75%
*
假如数组用满,他并不是将数组的每个索引全部占用
* 当我们用对象的hash值去&数组大小的时候,不避免会产生相同的索引
*
这样就会导致一个索引有可能存放两个不同key,这个时候使用单向链表解决
*
首先数组索引指向新创建的entry,新entry有一个next属性会指向原来的entry对象,形成一个单向链表
* 其实如果使用单向链表存储数据的时候,已经违背了map设计的思想
*
所以我们最好重写每一个对象的hashcode方法
* 当我们的map里面的数组进行扩容的时候,当扩容完毕,首先散列我们现有存储的对象,尽量吧存在链表的地方给分开,提高查询效率
*
* Entry:记录
*
我们map为了存放数据,所以专门创建的一个静态内部类
*
类似于我们数组中的一个元素
*
entry里面有两个属性
*
key
*
value
*
另外为了避免一些问题:不同hash算出相同index
*
next:
*
另外为了查找更加的快捷,专门记录了key的hash值
*
hash:比较的时候线比较hash值
*
* hashmap中可以存放空值
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量