java中常见的几种List 和 Map的扩容问题

你好,我是吴计可师,一个工作十多年的后端开发,曾就职京东、阿里等多家互联网头部企业。

点击下方👇关注公众号,带你一起复习后端技术,看看面试考点,补充积累技术知识,每天都为面试准备积累


在 Java 中,List 和 Map 的扩容是非常重要的概念,因为它直接影响性能,特别是在处理大量数据时。下面详细介绍几种常见的 List 和 Map 的扩容方式以及它们的扩容因子。


01
ArrayList 的扩容方式与扩容因子


ArrayList 是一个基于数组实现的动态数组。当你向 ArrayList 中添加元素并且容量不足时,ArrayList 会自动扩容。扩容的方式如下:

  • 初始容量:默认情况下,ArrayList 的初始容量是 10

  • 扩容因子:ArrayList 在扩容时,会将容量增加为原容量的 1.5 倍(即原容量的 150%)。

具体扩容过程:

假设 ArrayList 当前的容量是 n,当需要添加元素时,如果容量不够,它会扩容为 n + n / 2,即 1.5 * n。

例子:

  • 初始容量是 10。

  • 如果添加第 11 个元素,扩容后容量变为 15。

  • 如果添加第 16 个元素,扩容后容量变为 22(即 15 * 1.5)。

扩容因子:

ArrayList 的扩容因子是 1.5。具体来说,当集合元素数量超过当前容量时,ArrayList 的容量会增加到原容量的 150%。

如何设置扩容因子:

可以通过构造函数设置 ArrayList 的初始容量,但不能直接设置扩容因子。例如:

// 设置初始容量为 20ArrayList<String> list = new ArrayList<>(20);

02
LinkedList 的扩容方式


LinkedList 是基于双向链表实现的,它的扩容方式与 ArrayList 不同,因为它不使用数组来存储数据,而是使用节点(每个节点包含数据和指向前后节点的指针)。因此,LinkedList 不需要进行扩容操作,它不会像 ArrayList 那样在内存中分配固定的大小。

无固定容量:LinkedList 根据实际需要动态分配内存,当添加或删除节点时,它会动态地分配内存。因此,LinkedList 不需要考虑扩容因子。


03
HashMap 的扩容方式与扩容因子


扩容方式:

HashMap 使用数组和链表(或红黑树)来存储键值对。在存储的键值对数量超过当前容量的负载因子时,HashMap 会自动扩容。默认情况下,HashMap 的扩容是基于以下规则:

初始容量:默认容量是 16

扩容因子:负载因子默认值为 0.75

扩容过程

当 HashMap 中的元素个数超过当前容量的 负载因子(load factor)时,HashMap 会进行扩容。

公式:

  • threshold = capacity * load factor

例如,默认初始容量是 16,负载因子是 0.75。当 HashMap 中的元素数量超过 16 * 0.75 = 12 时,就会进行扩容。

扩容因子:HashMap 的容量会增加到原容量的 2 倍,即原容量的 200%。

如何设置扩容因子:

你可以通过构造函数来设置 HashMap 的初始容量和负载因子。

// 初始容量为 32,负载因子为 0.8HashMap<String, Integer> map = new HashMap<>(32, 0.8f);

04
LinkedHashMap 的扩容方式


LinkedHashMap 是 HashMap 的一个子类,维护了键值对的插入顺序。它的扩容方式与 HashMap 基本相同,因为它继承了 HashMap 的实现。

扩容规则:同样基于负载因子,当存储的元素个数超过 capacity * load factor 时进行扩容。

扩容因子:容量扩展到原容量的 2 倍,负载因子默认为 0.75。


05
TreeMap 的扩容方式


TreeMap 是基于红黑树实现的,它不像 HashMap 和 ArrayList 那样基于数组或链表存储元素。因此,TreeMap 并不需要进行扩容操作。红黑树的结构能够根据键的顺序自动平衡,因此不涉及扩容因子的概念。



06
总结


容器类扩容方式扩容因子初始容量备注
ArrayList1.5 倍扩容1.510初始容量 10,扩容为 1.5 倍。
LinkedList不涉及扩容无扩容因子无固定容量基于链表实现,动态分配内存。
HashMap容量翻倍扩容200%16默认负载因子 0.75,容量翻倍。
LinkedHashMap容量翻倍扩容200%16基于 HashMap,保持插入顺序。
TreeMap不涉及扩容无扩容因子无固定容量基于红黑树实现,自动平衡结构。

总的来说,ArrayList 和 HashMap 的扩容方式最为常见,其中 ArrayList 基于 1.5 倍扩容,HashMap 基于负载因子和容量翻倍扩容。而 LinkedList 和 TreeMap 则不涉及容量扩展的概念,因为它们的实现方式不同。

今天的内容就分享到这儿,喜欢的朋友可以关注,点赞。有什么不足的地方欢迎留言指出,您的关注是我前进的动力!

END


扫码关注

一起积累后端知识
不积跬步,无以至千里
不积小流,无以成江海

喜欢此内容的人还喜欢

谈谈id那些事(五)——美团的 Leaf 的ID生成


一个阿里二面面试官必问的问题


谈谈id那些事(三)——阿里巴巴的 TDDL的ID生成


分享面试:mysql数据库索引失效的情况


面试常被忽略的问题——内存区域划分