一、核心接口
1、Collection:基本接口
1.1 List 接口
特性:有序集合,可包含重复元素。
- ArrayList
特点:随机访问速度快,中间插入删除速度较慢尾部操作较快。
底层:使用动态数组实现,由于数组的存储结构是连续的内存块,通过索引可以直接定位到任何一个元素,时间复杂度为 O(1),因此随机访问速度非常快,但是进行插入或删除操作时,尤其是在中间位置,可能需要移动大量元素以保持数组的连续性,因此在中间位置插入和删除操作较慢,在数组头尾的话插入和删除操作则较快
- LinkedList
特点:插入删除速度快,随机访问速度较慢。
底层:使用双向链表实现,每个节点包含三个部分,元素值、指向前一个节点的引用、指向下一个节点的引用,某个位置插入一个新元素,只需要调整相关节点的 next 和 previous 引用即可,删除一个元素时,只需要将该节点的前一个节点的 next 指向该节点的下一个节点,同时将下一个节点的 previous 指向前一个节点即可,时间复杂度通常为 O(1),因此插入删除速度快,但是随机访问某个位置的元素需要从链表头部或尾部开始,逐个节点进行遍历,直到找到目标位置,即O(n) 的时间复杂度
- Vector
特点:类似 ArrayList,但线程安全。
底层:Vector 对每个方法(add(), remove(), get()等)都进行了同步处理(synchronized 关键字),以确保线程安全
- Stack:
特点:继承自 Vector,实现栈的功能,支持后进先出(LIFO)。
底层:LIFO 意味着最后添加的元素最先被移除,比如通过push(E item)将元素按顺序 1、2、3 压入栈,则通过pop()移除并返回栈顶元素的顺序是3、2、1
1.2 Set 接口
特性:无序集合,不允许重复元素。
- HashSet:
特点:实现了Set,基于哈希表实现,不保证元素顺序。
底层:实际上是一个 HashMap 对象。具体来说,HashSet 使用 HashMap 的键 (key) 来存储集合中的元素,而所有的值 (value) 都使用一个固定的对象 PRESENT 来代替,HashSet 确保了元素的唯一性,因为 HashMap 不允许键重复。
- LinkedHashSet:
特点:继承自HashSet,具有插入顺序的哈希表实现。
底层:是一个 LinkedHashMap
- TreeSet:
特点:实现了Set,不允许重复元素,元素是有序的,插入、删除、搜索操作效率较高。
底层:TreeSet 通过 TreeMap 实现,调用 TreeMap 的 put、remove、clear等方法完成各种操作
1.3 Queue 接口
特性:用于按顺序排队的元素。
- PriorityQueue:
特点:实现了Queue ,元素按优先级排序。
底层:基于优先级堆(二叉堆)实现,默认是最小堆实现,在插入和删除时通过上浮和下沉操作来维护堆的性质,从而排序元素的优先级,元素按优先级顺序出队,优先级高的元素会比优先级低的元素先出队
- Deque:继承自Queue ,双端队列,可从两端进行插入和删除。
- ArrayDeque:
特点:实现了Deque,高效的两端操作和随机访问操作,对内存连续性要求高。
底层:使用循环数组(circular array)实现,将数组首尾相连,使用两个指针(head 指针指向队列的第一个元素,tail 指针指向队列的下一个插入位置)来管理循环数组,不直接支持在中间进行插入和删除操作。在两端插入和删除元素的时间复杂度为 O(1),但在扩展数组时可能需要 O(n) 的时间,通过索引访问元素的时间复杂度为 O(1)
- LinkedList:
特点:实现了Deque,既高效的两端操作和动态内存扩展收缩。
底层:使用双向链表(Doubly Linked List)实现,每个节点包含数据以及指向前一个和后一个节点的指针,由于每个节点需要额外的指针空间,内存开销较大。在链表的两端插入和删除元素的时间复杂度为 O(1),访问任意位置的元素需要从头或尾遍历,时间复杂度为 O(n)
2、Map:存储键值对的接口
- HashMap:
特点:不保证顺序的键值对映射。
底层:HashMap 是基于哈希表(哈希桶)实现的,通过对象的 hashCode 方法计算出一个哈希码,再经过某种散列函数转换为哈希表中的索引,然后在哈希表检查该索引位置是否已经有元素,没用则将元素存储在哈希表的相应位置(桶),有则处理哈希冲突(通常通过链地址法(意味着同一个桶(Bucket)中可能会存储多个数据),即链表(Java 8 及之后当链表长度超过一定阈值(默认是8)时,会将链表转换成红黑树确保操作性能),或者开放地址法(所有元素存储在哈希表的数组中,不使用额外的数据结构,而通过某种探测策略在数组中寻找下一个可用位置来存放冲突的元素,比如线性探测,就是按照一定的步长(计算下一个存储位置的增量值,比如1)依次检查下一个位置直到找到一个空位)。另外经过使用哈希表生成索引来存储元素,而不是按照插入顺序,所以无法保证键值对的顺序,不过这也使得插入、删除和查找操作通常可以在常数时间内完成,即 O(1) 时间复杂度
- LinkedHashMap:
特点:具有插入顺序的键值对映射。
底层:在HashMap的基础上,还维护了一个双向链表来记录元素的插入顺序。每个节点不仅包含键、值和哈希码,还包含指向前后节点的指针
- TreeMap:
特点:有序的键值对映射,键默认按自然顺序排序。
底层:TreeMap 使用红黑树来实现的,它是一种自平衡的二叉搜索树,操作的时间复杂度为O(log n) 。节点存储着父子节点的引用和键值对数据。由于红黑树的结构依赖于对节点进行比较,以决定节点在树中的位置,来保持红黑树的有序性和自平衡,所以可以保证存储有序的键值对映射。此默认比较器为按照自然顺序的比较器,如果需要按不同的顺序存储数据,就需要使用不同的比较器在创建 TreeMap 时提供相应的比较器
- Hashtable:
特点:线程安全的哈希表实现。
底层:通过哈希表来实现存储和快速查找,所有方法都是同步的。Hashtable 不允许键或值为 null
- Properties:
特点:专门用于维护配置文件中的键值对。
底层:继承自 Hashtable
eg:读取配置文件
eg:写入配置文件
eg:获取属性值
二、特点
- 类型安全
-通过泛型保证类型安全
泛型(Generics)是 Java 中的一种机制,它允许在定义类、接口和方法时使用类型参数。。这些类型参数在实际使用时可以指定具体的类型,从而确保在编译时进行类型检查,保证类型安全。(比如List接口定义为List<T> , T
是一个泛型类型参数,假如泛型类型为String,给集合添加非 String
类型的元素(例如 stringList.add(123)
)就会导致编译错误)
- 动态扩展
-大多数集合类可以根据需要动态扩展
指的是集合类在需要时可以自动调整其容量,以适应添加新元素的需求。这一特性主要应用于那些基于数组实现的集合类,如 ArrayList
(
默认情况下,ArrayList
的初始容量是 10,当数组容量不足时,常会将其容量增加约 50%。例如,如果当前容量是 10,新的容量将是 15)
和 Vector(
默认的扩展机制是将容量翻倍)
- 高性能
-通过优化算法和数据结构,提供高效的操作
不同的集合类采用了不同的数据结构,以提高其在特定操作上的性能(比如ArrayList动态数组,LinkedList双向链表,HashSet/HashMap哈希表,TreeSet/TreeMap红黑树);使用了多种高效的算法来优化操作性能(比如Collections.binarySearch二分查找,HashMap哈希算法,
Collections.sort归并排序算法);并发优化(比如Collections.synchronizedList
和 Collections.synchronizedMap
来动态地创建线程安全的集合,比Vector
和 Hashtable性能更好
)
- 丰富的功能
-提供丰富的操作方法,如排序、搜索、线程安全等
主要体现在它提供了许多内置的方法和工具类,如下
三、工具类
Collections
提供操作集合的静态方法,如排序、搜索、同步集合创建等。
它提供了一系列静态方法,用于操作和处理集合
对自身的操作
增
1、填充
fill(List<? super T> list, T obj):用指定元素填充列表。
查
2、查找
binarySearch(List<? extends Comparable<? super T>> list, T key):使用二分法搜索指定列表,以获得指定对象的索引(适用于有序集合,效率较高)
改
3. 排序
sort(List<T> list):对指定的列表按自然顺序进行升序排序。
sort(List<T> list, Comparator<? super T> c):根据指定比较器产生的顺序对列表进行排序。
4、反转
reverse(List<?> list):反转指定列表中元素的顺序
5、交换
swap(List<?> list, int i, int j):交换列表中指定位置的元素
集合间的操作
查
1、集合最值
min(Collection<? extends T> coll):返回给定集合中的最小元素
max(Collection<? extends T> coll):返回给定集合中的最大元素
2、频率统计
frequency(Collection<?> c, Object o):返回指定集合中等于指定对象的元素个数
改
3、拷贝
copy(List<? super T> dest, List<? extends T> src):将源列表中的所有元素复制到目标列表中(目标集合 dest
必须至少与源集合 src
一样长,否则会抛出 IndexOutOfBoundsException
异常)
执行上述代码后,dest
集合的内容将会是:
[a, b, c]
4、同步
synchronizedList(List<T> list):返回指定列表的同步列表(线程安全)(这个同步列表包装了原始列表,并通过内部的同步机制(通常是使用 synchronized
关键字)来保证多线程环境下的线程安全,可能会带来一定的性能开销,单线程下不必使用)
对比Vector由于只在需要时才同步,并且可以选择性同步,性能通常比 Vector
更好
5、不可变
unmodifiableList(List<? extends T> list):返回指定列表的不可修改视图
6、合并
addAll(Collection<? super T> c, T... elements):将所有指定元素添加到指定集合中