Java集合框架(四)Map

Map接口继承树

在这里插入图片描述


Map接口概述

● Map与Collection并列存在。用于保存具有 映射关系 的数据:key-value
● Map 中的 key 和 value 都可以是任何引用类型的数据
● Map 中的 key 用Set来存放, 不允许重复,即同一个 Map 对象所对应的类,须重写hashCode()和equals()方法。
● 常用String类作为Map的“键”
● key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value
● Map接口的常用实现类:HashMap、TreeMap、LinkedHashMap和Properties。其中,HashMap是 Map 接口使用频率最高的实现类。

map结构
在这里插入图片描述


Map接口:常用方法

添加 、 删除、修改操作 :

Object put(Object key,Object value):将指定key-value添加到(或修改)当前map对象中
void putAll(Map m):将m中的所有key-value对存放到当前map中
Object remove(Object key):移除指定key的key-value对,并返回value
void clear():清空当前map中的所有数据

元素 查询的操作:

Object get(Object key):获取指定key对应的value
boolean containsKey(Object key):是否包含指定的key
boolean containsValue(Object value):是否包含指定的value
int size():返回map中key-value对的个数
boolean isEmpty():判断当前map是否为空
boolean equals(Object obj):判断当前map和参数对象obj是否相等

元视图操作的方法:

Set keySet():返回所有key构成的Set集合
Collection values():返回所有value构成的Collection集合
Set entrySet():返回所有key-value对构成的Set集合

map遍历

Map map = new HashMap();
//map.put(..,..)省略
System.out.println("map的所有key:");
Set keys = map.keySet();// HashSet
for (Object key : keys) {
    System.out.println(key + "->" + map.get(key));
}
System.out.println("map的所有的value:");
Collection values = map.values();
Iterator iter = values.iterator();
while (iter.hasNext()) {
    System.out.println(iter.next());
}
System.out.println("map所有的映射关系:");
// 映射关系的类型是Map.Entry类型,它是Map接口的内部接口
Set mappings = map.entrySet();
for (Object mapping : mappings) {
    Map.Entry entry = (Map.Entry) mapping;
    System.out.println("key是:" + entry.getKey() + ",value是:" + entry.getValue());
}

Map 实现类之一:HashMap

● HashMap是 Map 接口 使用频率最高的实现类。
● 允许使用null键和null值,与HashSet一样,不保证映射的顺序。
● 所有的key构成的集合是Set:无序的、不可重复的。所以,key所在的类要重写:equals()和hashCode()
● 所有的value构成的集合是Collection:无序的、可以重复的。由于containsValue方法需要判断value是否存在,所以,value所在的类要重写:equals()。不然即使value存在,也无法判断。
● 一个key-value构成一个entry
● 所有的entry构成的集合是Set:无序的、不可重复的
● HashMap 判断两个 key 相等的标准是:两个 key 通过 equals() 方法返回 true,hashCode 值也相等。
● HashMap 判断两个 value 相等的标准是:两个 value 通过 equals() 方法返回 true。


HashMap的底层实现原理、源码分析

jdk7源码分析:
HashMap map = new HashMap();

  1. 在实例化以后,底层创建了长度16的一维数组Entry[] table;
  2. 当执行多次put操作后,再次执行map.put(key1, value1);
  3. 计算key1的哈希值,通过散列函数计算后,得到在Entry数组中的存放位置;
  4. 判断此位置上面是否为空,若为空,则添加成功;
  5. 若不为空,则循环此位置上的所有元素(以链表形式存放),比较key1与所有元素key的哈希值;
  6. 如果key1的哈希值与该位置上所存在的所有元素的哈希值都不相同,添加成功;
  7. 若果key1的哈希值与某个元素的key2哈希值相同,继续通过equals比较key1与key2的值;
  8. 如果equals返回false,添加成功;
  9. 如果equals返回true,使用value1替换value2。
    注:扩容方式为扩容为原来容量的2倍,并将原有的数据复制过来。
    在这里插入图片描述

jdk8源码分析:
与jdk在如下方面不同

  1. new HashMap():底层没有创建一个长度为16的数组,在put第一个元素时创建。
  2. 底层数组是:Node[],而非Entry[];
  3. jdk7底层结构:数组+链表;jdk8:数组+链表+红黑树。
    当数组的某个索引位置上链表存放的元素个数 >= 7 且当前数组的长度 > 64 时,此时该索引位置上的所有数据改为使用红黑树存储。(若数组长度不大于64,进行扩容)。

HashMap的存储结构

JDK 7及以前版本:HashMap是数组+链表结构(即为链地址法)。
JDK 8版本发布以后:HashMap是数组+链表+红黑树实现。
下图为jdk7HashMap中的key存放方式:数组 + 链表。
在这里插入图片描述
在这里插入图片描述

DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16
MAXIMUM_CAPACITY : : HashMap的最大支持容量,2^30
DEFAULT_LOAD_FACTOR :HashMap的默认加载因子 : 0.75f
TREEIFY_THRESHOLD :Bucket中链表长度大于该默认值,转化为红黑树 :8
UNTREEIFY_THRESHOLD :Bucket中红黑树存储的Node小于该默认值,转化为链表:6
MIN_TREEIFY_CAPACITY :桶中的Node被树化时最小的hash表容量。(当桶中Node的数量大到需要变红黑树时,若hash表容量小于MIN_TREEIFY_CAPACITY时,
                       此时应执行resize扩容操作这个MIN_TREEIFY_CAPACITY的值至少是TREEIFY_THRESHOLD的4倍。)
table :存储元素的数组,总是2的n次幂
entrySet: :存储具体元素的集
size :HashMap中存储的键值对的数量
modCount :HashMap扩容和结构改变的次数。
threshold :扩容的临界值,=容量*填充因子
loadFactor: :填充因子
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值