之前在学校上课时已经学习过关于集合类的一些知识,但是这两天发现对于集合类的一些点还是不太清楚,很多内容很容易混淆在一起,在这里,我将一些我记不太清的点做一些整理
集合结构图
Java中的集合类都是由Java.util包提供
由上图所示,Java集合类中最主要的是两个核心的接口:
Collection和Map
1 Collection接口:
Collection接口有两个子接口,为Set接口和List接口(下面将做讲解)
在JDK1.5之后Collection追加具有泛型应用,使得避免了ClassCastException
在JDK1.8之后Collection接口还追加了从集合获取连续的或者并行流Stream
1.1 List接口:
(1)List接口是Collection接口的子接口
(2)List接口是一个元素有序,可以重复,元素可以为null的集合
(3)List接口下有三种常见的实现子类:ArrayList,LinkedList,Vector(后面做具体讲述)
List VS Array:
共同点:
都可以使用一组同类型的元素
都使用下标进行搜索
不同点:
数组可以存储任何类型元素
List不可以存储基本数据类型,必须为包装类
数组效率更高,因为List要额外维护一些内容,效率会低一些
总结:
容量固定时优先使用数组,容纳类型更多更高效
容量不固定,List更有优势,因为List不需要扩容
1.2.1 ArrayList
JDK1.2提出
List接口的实现类中,最常用的是ArrayList
ArrayList是以数组实现的,遍历时很快,但是在插入和删除的时候都需要移动后面的元素,因此效率会差一些
特点:
(1)ArrayList的实现是不同步的,因此线程不安全
(2)容量固定,若达到阙值,会扩容
(3)元素有序,即元素的输入输出顺序一致
(4)元素可以为null
(5)查找效率高,ArrayList中的size(),isEmpty(),set(),iterator(),Listlterator()方法的时间复杂度为O(1),
add()及其他方法的时间复杂度为O(n)
(6)占用空间小:相对于LinkedList来说ArrayList不用占用额外空间维护链表的结构
1.2.2 LinkedList
LinkedList类是List接口的实现类
LinkedList是以链表实现的,在插入,删除时只需要改变前后两个节点的指针指向
节点结构见下图
特点:
(1)效率高,头插头删,尾插尾删,获取指定节点,指点节点的添加删除的时间复杂度都为O(1)
(2)双向链表实现
(3)元素有序,即输出顺序与输入顺序一致
(4)允许元素为null
(5)所有指定位置的操作都是从开头开始遍历进行的
(6)不同步,线程不安全
LinkedList VS ArrayList:
ArrayList:
基于数组实现,在数组中搜索和读取数据很快,ArrayList获取元素的时间复杂度为O(1)
ArrayList在添加,删除元素时,该元素后面的元素都要后移,因此ArrayList添加,删除数据的效率不高
ArrayList有固定容量,若达到固定的阙值时需要扩容,此时会影响效率
LinkedList:
基于双向链表实现,添加,删除元素只会影响相邻点,开销低
只能顺序遍历,无法按照索引获得元素,因此查询效率并不高
LinkedList没有固定容量,不需要扩容
LinkedList需要更多的内存,因为LinkedList的每个节点需要占用额外的存储空间来存放前后节点的信息
1.2.3 Vector:
JDK1.0提出,现在已经很少使用
特点:
(1)底层是可增长的数组组成的
(2)Vector在扩容时默认扩大两倍
(3)线程同步,线程安全
(4)在插入大量元素之前,最好先增加Vector的容量,这样可以减少申请内存的次数
(5)每次使用都要获取锁,效率低
Vector VS ArrayList
相同点:
都是基于数组实现的
都支持随机访问
默认容量为10
都有扩容机制
不同点:
Vector是JDK1.0出现,ArrayList是JDK1.2出现的
Vector比ArrayList多一种迭代机制Enumeration
(Vector支持Iterator,Listlterator,foreach,Enumeration;ArrayList支持Iterator,Listlterator,foreach)
Vector线程安全,ArrayList线程不安全
Vector默认扩容2倍,ArrayList默认扩容1.5倍
1.2.3.1 Stack栈
特点:
(1)继承于Vector
(2)有5种创建Stack的方法(4种继承自Vector的构造方法,一种本身)
(3)采用数组实现
(4)除了push(),其他方法都同步
1.2 Queue接口
Queue继承Collection接口
Queue一般都是先进先出,但是也有一些特殊的队列例外
Queue一般情况下都不允许添加null元素
1.3 Set接口
Set接口 VS List接口
Set接口中的元素不允许重复的
List接口没有对Collection接口进行扩充,而List接口对Collection接口进行了扩充,所以Set接口中没有get()方法
Set接口下有两个常见的实现子类:HashSet,TreeSet(后面做具体讲述)
HashSet:
优先使用HashSet
特点:
(1)底层实现是HashMap
(2)无序存储,允许为null,但有且只有一个null,
(3)判断重复元素的时候要覆写Object中的hashCode()及equals()方法
TreeSet:
有序存储。默认为升序排序。不允许为null,要想使用自定义类作为TreeSet存储该类,必须覆写Comparable接口
HashMap VS TreeSet
HashSet的性能总比TreeSet好(特别是添加,查询等操作),因为TreeSet是需要额外的红黑树算法来维护元素的次序,只有当需要一个保持排序的Set的时候,才使用TreeSet,否则都应使用HashSet
使用TreeSet过于麻烦,因为要额外覆写Comparable接口
2 Map接口:
Java中Map接口和Collectio为同一等级的集合根接口
Map的实现类有4种:
Hashtable:线程安全
HashMap:速度快,但没有顺序
TreeMap:有序,效率比HashMap低
LinkedHashMap:结合HashMap与TreeMap的优点,有序,效率也可以,但是效率比HashMap低
之前写关于HashMap与HashTable区别的博客
总结:
(1)没有重复的key
(2)每个key都只能对应一个value,多个key可以对应一个value
(3)key.value都可以引用任何类型的数据,包括null
(4)Map取代了古老的Dictionary抽象类
文中图片来自网络,若有侵权,请联系我