数组和集合的区别:
1、数组是固定长度的数据结构,一旦创建长度就无法改变,集合是动态长度数据结构,可根据需求动态增加或减少元素。
2、数组包含基本数据类型和对象,而集合只能包含对象。
3、数组可以直接访问元素,而集合需要通过迭代器或其他方法访问元素。
常用集合类:
1、ArrayList:动态数组,实现了List接口,支持动态增长(超限扩容到size+size>>2)。
2、LinkedList:双向链表,实现了List接口,支持快速插入和删除操作。
3、HashMap:基于哈希表实现,存储键值对,数组加链表形式,哈希冲突时使用拉链法将冲突的键值对存储到额外维护的链表中。
4、HashSet:基于HashMap实现的Set集合,用于存储唯一元素。
5、TreeMap:基于红黑树实现的有序Map集合,可以按照键的顺序进行排序。
6、LinkedHashMap:基于哈希表和双向链表实现的Map集合,保持插入顺序或访问顺序。
7、PriorityQueue:优先队列,可以按照比较器或元素的自然顺序进行排序。
List接口
List是有序的Collection,使用此接口能够精确控制每个元素的插入和删除位置,允许根据索引访问元素。常用的实现类有LinkedList,ArrayList,Vector,Stack。
ArrayList:容量可变的非线程安全列表。底层使用数组。实现。每次插入新元素时会检查容量是否充足。扩容时默认创建1.5倍的新数组并进行原数组的复制。ArrayList保留了数组的快速查询特性,但同时也保留了插入和删除速度慢的缺点。
Vector:线程安全的动态数组,内部方法经过synchronzed修饰。扩容时会创建新数组并复制。
LinkedList:本质是一个双向链表,有更快的插入和删除速度,但查询较慢。
Map接口
Map是一个键值对集合,存储键、值之间的映射,Key无序且唯一,Value不要求有序且允许重复。Map并未继承Collection接口,从Map集合检索元素时,只要给出Key就会返回对应的值对象。主要实现有TreeMap,HashMap,LinkedHashMap,CurrentHashMap.
HashMap:由数组和链表组成,数组是HashMap的存储主体,链表用于解决Hash冲突。每个数组元素指向一个对应的链表。
“拉链法”:将哈希冲突的键值对存储在数组元素对应的链表中。Java8后链表长度大于阈值(默认为8)后会转化为红黑树,以减少搜索时间。
LinkedHashMap:继承自HashMap。在其基础上增加了一条双向链表,以维护插入元素的顺序。
TreeMap:红黑树(自平衡的排序二叉树)
HashTable:线程安全的HashMap(方法使用synchronzed同步锁修饰,锁整表)
ConcurrentHashMap:线程安全的HashMap(使用volatile+CAS或synchronzed同步锁,对每个元素加锁)。put操作时,若Key不存在,则使用CAS操作赋值为当前值,若Key已经存在,则使用synchronzed关键字申请锁,再进行链表的新增操作。
Set接口
Set不允许存在重复元素,set集合的元素一般是无序的,且不支持通过索引访问。常用的实现有HashSet、LinkedHashSet和TreeSet
HashSet:基于HashMap实现,HashMap的Key即为HashSet存储的元素,所有Key都使用相同的Value,一个名为PRESENT的Object常量,使用Key保证元素唯一性,但不保证有序性,也不是线程安全(HashMap不是线程安全)。
LinkedHashSet:继承自HashSet,基于LinkedHashMap实现,使用双向链表维护元素插入顺序。
TreeSet:基于TreeMap实现,添加元素到集合时按照比较规则将其插入合适的位置,保证插入后的集合仍然有序。