🌟文章中的图很重要
1.接口继承关系和实现
集合类存放于 Java.util 包中,主要有 3 种:set(集)、list(列表包含 Queue)和 map(映射)。
1. Collection:Collection 是集合 List、Set、Queue 的最基本的接口。
2. Iterator:迭代器,可以通过迭代器遍历集合中的数据
3. Map:是映射表的基础接口
2.List
Java 的 List 是非常常用的数据类型。List 是有序的 Collection。Java List 一共三个实现类:
分别是 ArrayList、Vector 和 LinkedList。
2.1. ArrayList(数组)
ArrayList 是最常用的 List 实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要将已经有数组的数据复制到新的存储空间中。当从 ArrayList 的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。
在Java中,ArrayList
的默认初始容量是10。当向ArrayList
中添加元素时,如果其大小不足以容纳所有元素,它会进行扩容,扩容的大小通常是原容量的1.5倍。
扩容操作涉及到两个因素:
-
扩容大小的增长:ArrayList每次扩容的时候会增长原来数组大小的一半。
-
初始容量:ArrayList可以有一个初始容量,这个容量在构造ArrayList的时候可以指定。
扩容操作的具体步骤如下:
-
计算新的容量:newCapacity = oldCapacity + (oldCapacity >> 1)
-
创建新的数组:新的数组大小为newCapacity
-
复制元素到新数组:将旧数组中的元素复制到新数组中
-
引用新数组:ArrayList的底层数组引用新数组
2.2. Vector(数组实现、线程同步)
Vector 与 ArrayList 一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一
个线程能够写 Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,
访问它比访问 ArrayList 慢。
2.3. LinkList(链表)
LinkedList 是用链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较
慢。另外,他还提供了 List 接口中没有定义的方法,专门用于操作表头和表尾元素,可以当作堆
栈、队列和双向队列使用。
2.4 copyOnWriteArrayList(线程安全)
CopyOnWriteArrayList详解https://www.cnblogs.com/yangfei629/p/11530968.html
背景
java诞生之初 就有线程安全的Vector,但Vector对读写都是通过synchronized关键字来同步的,性能并不好。
且Vector每次扩容是原来的1倍,存在内存浪费的可能。
对于线程安全的List JDK提供了CopyOnWriteArrayList
缺点
a. 每次修改都会拷贝数组 占用内存 写性能不高
b.修改的过程中 数据依赖读的是老的数据 ,只能保证最终一致 不能保证强一致性
使用场景
1、多线程 读多写少。
2、不要求数据强一致性。
否则推荐使用Collections.synchronziedList
3.面试问题
3.1 LinkedeList和ArrayList的区别
linkedlist和arraylist的区别是什么-常见问题-PHP中文网
1、数据结构不同
ArrayList是Array(动态数组)的数据结构,LinkedList是Link(链表)的数据结构。
2、效率不同
当随机访问List(get和set操作)时,ArrayList比LinkedList的效率更高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。
当对数据进行增加和删除的操作(add和remove操作)时,LinkedList比ArrayList的效率更高,因为ArrayList是数组,所以在其中进行增删操作时,会对操作点之后所有数据的下标索引造成影响,需要进行数据的移动。【视频教程推荐:Java视频教程】
3、自由性不同
ArrayList自由性较低,因为它需要手动的设置固定大小的容量,但是它的使用比较方便,只需要创建,然后添加数据,通过调用下标进行使用;而LinkedList自由性较高,能够动态的随数据量的变化而变化,但是它不便于使用。
4、主要控件开销不同
ArrayList主要控件开销在于需要在lList列表预留一定空间;而LinkList主要控件开销在于需要存储结点信息以及结点指针信息。
3.2 arraylist将旧数组中的元素复制到新数组中后,旧数组怎么处理
在Java中,当你使用ArrayList的toArray方法将ArrayList中的元素复制到一个新的数组中时,旧的数组(如果是直接由ArrayList内部管理的数组)通常不需要进一步处理。ArrayList会管理这个数组的大小和内容,包括扩容和元素添加/移除。
如果你指的是一个明确的旧数组(可能是之前由ArrayList使用的内部数组,或者是另一个独立的数组),并且你已经将这些元素转移到了一个新的数组中,那么你可以考虑将这个旧数组的引用设置为null,以帮助垃圾收集器更早地回收它,如果这个数组不再被其他对象引用的话。