Map双列集合总结

这篇文章记录了学习Java过程中对Map集合的总结

一、Map

为什么叫双列集合?因为Map集合中每一个元素包含两个部分,一个是键(key)一个是值(value)

为什么Collecion是单列集合?因为Collention集合中每个元素就是一个单一的数据

二、HashMap

1. 底层结构----哈希表

1.1 特点

  1. 底层是哈希表就有哈希表所有特性:不重复无序查询快(只是针对键,对值没有要求
  2. 可以null键null值,但null键只能有一个(因为不重复)
  3. 添加元素,键第一次出现是添加,第二次出现是修改

1.2 关于HashMap集合的基本常识

1.2.1默认容量:16

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

1.2.2 默认负载因子:0.75

static final float DEFAULT_LOAD_FACTOR = 0.75f;
HashMap中元素达到这个比例时,进行扩容,新容量为之前两倍
  1. 负载因子衡量的是一个散列表(哈希表)空间的使用程度,负载因子越大表示散列表的装填程度越高,反之越小
  2. 如果负载因子越大,对空间的利用更充分,然而后果是查找效率的降低;如果负载因子太小,那么散列表的数据将过于稀疏,对空间造成严重浪费
  3. 默认负载因子0.75是对空间和时间效率的一个平衡的选择。当容量超过这个比例,resize后的HashMap容量是之前的两倍。

1.2.3 扩容机制

当hashMap中的元素越来越多时,哈希表的离散性就越来越低,发生哈希冲突的概率也越来越高,为了避免哈希冲突,提高查询效率,就会对哈希表进行扩容,扩容的过程时非常消耗性能的。所以如果我们已经预知HashMap中元素的个数,那么预设元素的个数能够有效的提高HashMap的性能。

1.2.4 扩容过程

当集合中的数据长度达到容量的0.75倍时(capacity * loadFactor),会自动将HashMap容量扩大到原来的两倍,并且重新计算原哈希表中所有元素在新哈希表中的存储位置

1.2.5 扩容过程分析

默认情况下,哈希表(数组)大小为16,loadFactor为0.75,那么当HashMap中元素个数超过16*0.75=12的时候,就把数组的大小扩展为 2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置

1.2.6 为什么建议在定义时候要声明容量

阿里开发规范
阿里巴巴《Java开发手册》第1章编程规范,第5节集合处理的第9条规定如下:
如果已知元素数量(假如128)但不指定容量(默认16),那么就会造成哈希表频繁的扩容造成性能降低。

1.2.7. 如何解决性能消耗

1、使用Google的Map工具类

//用在Maven里,需要导入坐标
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1.1-jre</version>
</dependency>
Map<Integer, Integer> map2 = Maps.newHashMapWithExpectedSize(3);
map2.put(1, 1);
map2.put(2, 2);
map2.put(3, 3);
System.out.println("map2:" + map2);

2、在声明HashMap时就预设容量

HashMap map = new HashMap(8);//容量为2的幂次方

三、LinkedHashMap

1.1 特点:有序(指存取顺序)

1.2 底层实现----哈希表和链表

  • 原理:底层结构依然是哈希表,只是每个键值对额外多了一个双链表机制,记录存储的顺序

四、TreeMap

1.1 特点:不重复,无索引,可排序(只能针对键排序)

五、比较难懂的方法

要说Map集合中比较难懂的方法,我相信很多同学在entrySet()方法上栽过跟头,在我第一次学的时候也被这个方法绕晕了,下面就重点解释一下:

这是官方的解释:返回一个此映射中包含的映射的set视图

 
Set<Map.Entry<K,V>> entrySet() Returns a Set view of the mappings contained in this map

什么意思呢?也就是说,Map集合的元素是一个键值对,把这个键值对当作一个元素存到了Set集合中,可以看到Set集合他的泛型是一个Map.Entry<K,V>类型

看懂了木有,也就是说,把键值对当作一个整体,存放到了Set中,Set集合中每个元素就是一个键值对类型(这个词不准确哈,只是为了好理解)

Set集合中是一个Map.Entry<K,V>类型,就可以用Entry提供的方法获取键和值

posted @ 2023-04-05 21:21  星眼小橘  阅读(29)  评论(0编辑  收藏  举报