集合框架学习(持续更新)
Java集合框架总体结构图
Collection 接口
定义集合基本方法
1
|
int size();
|
AbstractCollection 抽象类
实现Collection接口中部分方法
boolean isEmpty()
校验集合是否为空
boolean contains(Object o)
校验集合是否包含o元素,该方法中会使用到迭代器iterator()
方法
Object[] toArray()
把集合转换成数组,该方法中会使用到迭代器iterator()
方法,该方法的实现有必要看一下。在初始化数组时,如果长度不够,是按照cap + (cap >> 1) + 1
的方式增加数组长度的,如果长度过长,再使用Arrays.copyOf(T[] original, int newLength)
方法重置数组长度
T[] toArray(T[] a)
暂定解释,这个方法有点没太理清楚
boolean add(E e)
直接抛出UnsupportedOperationException异常,默认不支持该操作,后续需要重写该方法
boolean remove(Object o)
使用迭代器,以o是否为null分别做remove操作,如果有remove操作,返回true
boolean containsAll(Collection<?> c)
调用boolean contains(Object o)
方法循环遍历,仅有集合中包含c所有值,才返回true
boolean addAll(Collection<? extends E> c)
调用boolean add(E e)
方法,只要新增成功一次就返回true
boolean removeAll(Collection<?> c)
使用迭代器,循环遍历当前集合,调用boolean contains(Object o)
判断c集合是否包含当前元素,如果包含,则使用迭代器的remove()
方法进行删除
boolean retainAll(Collection<?> c)
与boolean removeAll(Collection<?> c)
方法类似,只不过是删去c集合中不包含的元素
void clear()
使用迭代器,循环便利当前集合,使用迭代器的remove()
方法依次删除元素
String toString()
使用迭代器,循环遍历集合元素,通过StringBuilder
组合元素
List 接口
继承了Collection接口,List接口又另外定义了一些方法
1
|
int size();
|
AbstractList 抽象类
实现List接口,继承AbstractCollection抽象类
boolean add(E e)
调用add(int index, E element)
方法,在集合末尾增加元素,只要增加成功,就返回true
abstract public E get(int index)
待实现
E set(int index, E element)
直接抛出UnsupportedOperationException异常,默认不支持该操作,后续需要重写该方法
void add(int index, E element)
直接抛出UnsupportedOperationException异常,默认不支持该操作,后续需要重写该方法
E remove(int index)
直接抛出UnsupportedOperationException异常,默认不支持该操作,后续需要重写该方法
int indexOf(Object o)
获取listIterator()
返回的ListIterator
迭代器根据o是否为null分别做处理,如果按从前往后顺序集合中有o这个元素,则返回o元素的下标,否则返回-1
int lastIndexOf(Object o)
跟int indexOf(Object o)
方法类似,获取listIterator()
返回的ListIterator
迭代器根据o是否为null分别做处理,如果按从后往前顺序集合中有o这个元素,则返回o元素的下标,否则返回-1
void clear()
调用removeRange(int fromIndex, int toIndex)
方法,删去从0到集合末尾的所有元素
boolean addAll(int index, Collection<? extends E> c)
先校验index是否越界,然后循环在数组index的位置依次插入c中元素,只要插入成功一条记录就设置返回值为true
Iterator iterator()
返回new Itr()
ListIterator listIterator()
返回listIterator(0)
方法
ListIterator listIterator(final int index)
先校验index是否越界,然后返回new ListItr(index)
List subList(int fromIndex, int toIndex)
根据当前集合是否是RandomAccess
接口的实现类,如果是,则返回RandomAccessSubList
类型fromIndex,toIndex
之间的子集合;如果不是,则返回SubList
类型fromIndex,toIndex
之间的子集合
boolean equals(Object o)
当前集合和o集合(假设o是List接口的实现类)分别根据ListIterator<E> listIterator()
方法获取迭代器,然后元素依次比较,直至出现不相同的为止。完全相同返回true,否则返回false
int hashCode()
返回当前集合的hashCode值,代码有必要直接贴出来
1
|
public int hashCode() {
|
AbstractList$Itr 内部类
直接贴代码介绍
1
|
private class Itr implements Iterator<E> {
|
AbstractList$ListItr 内部类
1
|
// 可以指定从集合中哪个位置开始的迭代器
|
AbstractList/SubList AbstractList中非public的类
继承AbstractList
抽象类,构造方法中有fromIndex
和toIndex
入参以便重新设计子集合,该类中把AbstractList
没有实现的方法都具体实现了一下,没有什么特别难理解的地方,就不单独贴出来具体代码
AbstractList/RandomAccessSubList AbstractList中非public的类
继承SubList类,实现RandomAccess
接口,就重写了一下List<E> subList(int fromIndex, int toIndex)
这个方法,返回的子集合是RandomAccessSubList
类型
ArrayList 类
继承AbstractList抽象类,实现List,RandomAccess,Cloneable,Serializable接口,该类中有2个属性
1
|
private transient Object[] elementData; //ArrayList的实现方式其实还是用数组的方式进行的
|
ArrayList(int initialCapacity) 构造方法
根据传入的集合长度,初始化一个等长的elementData
ArrayList() 构造方法
默认初始化一个长度为10的elementData
ArrayList(Collection<? extends E> c) 构造方法
c集合调用toArray()
方法返回的数组赋值到elementData
中,并获取elementData
的长度设置到size
中
void trimToSize()
把集合的长度缩短至集合elementData.length
,也就是把集合末尾未使用到的位置给移除掉。modCount
要自增一次,modCount
是AbstractList
中的属性,用来记录集合变更的次数
void ensureCapacity(int minCapacity)
对ArrayList实例进行扩容,以够容纳minCapacity
这么多元素。扩容时会让modCount
自增一次。
1
|
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //一些 VMs在数组里保留字头,试图分配更大数组时可能导致OutOfMemoryError:被请求数组的size超出VM界限。
|
int size()
直接返回size
属性
boolean isEmpty()
返回size == 0
int indexOf(Object o)
在elementData
从前往后查找o
元素第一次出现的位置,如果没找到,则返回-1
boolean contains(Object o)
调用indexOf(Object o)
方法,判断o
元素第一次出现的位置是否大于0,大于0也就意味着集合中包含断o
元素
int lastIndexOf(Object o)
在elementData
从后往前查找o
元素第一次出现的位置,如果没找到,则返回-1
Object clone()
调用父类的clone()
方法,并重置新集合的modCount
为零。该克隆为浅克隆
Object[] toArray()
把elementData
集合扩展到size
长度并返回
T[] toArray(T[] a)
暂定解释,这个方法有点没太理清楚
E get(int index)
先校验一遍index是否大于size(没有校验是否小于0,看注释的意思是,如果index小于0,在该校验前就会抛出ArrayIndexOutOfBoundsException),然后直接获取elementData[index]
set(int index, E element)
先校验一遍index是否小于size,然后elementData[index] = element
,返回index
位置原来的元素
boolean add(E e)
先调用ensureCapacityInternal(int minCapacity)
方法(入参为size+1)对elementData
数组进行扩容,然后再进行elementData[size++] = e
操作,最终返回true
void add(int index, E element)
1
|
public void add(int index, E element) {
|
E remove(int index)
1
|
public E remove(int index) {
|
boolean remove(Object o)
先for
循环找到o
元素的下标,然后使用remove(int index)
类似的逻辑做删除操作
void clear()
先modCount++
设置集合修改次数+1,然后for
循环elementData
,依次设置每个元素都为null
,最终设置size
为0
boolean addAll(Collection<? extends E> c)
放上代码更容易理解
1
|
public boolean addAll(Collection<? extends E> c) {
|
boolean addAll(int index, Collection<? extends E> c)
放上代码更容易理解
1
|
public boolean addAll(int index, Collection<? extends E> c) {
|
##### boolean removeAll(Collection<?> c)
返回batchRemove(c, false)
boolean retainAll(Collection<?> c)
返回batchRemove(c, true)
1
|
private boolean batchRemove(Collection<?> c, boolean complement) {
|
private void writeObject(java.io.ObjectOutputStream s)
实现Serializable接口是需要有writeObject方法的实现的,由于Object方法默认就有writeObject方法的实现,所以Serializable接口中未定义抽象方法,但如果想自定义序列化方法,则需要重新该方法
private void readObject(java.io.ObjectInputStream s)
实现Serializable接口是需要有readObject方法的实现的,由于Object方法默认就有readObject方法的实现,所以Serializable接口中未定义抽象方法,但如果想自定义序列化方法,则需要重新该方法
ListIterator listIterator(int index)
校验index是否是0到size之间的,然后返回new ListItr(index)
ListIterator listIterator()
返回new ListItr(0)
Iterator iterator()
返回new Itr()
List subList(int fromIndex, int toIndex)
先校验fromIndex
,toIndex
是否符合规则,然后返回new SubList(this, 0, fromIndex, toIndex)
ArrayList$Itr 内部类
跟AbstractList$Itr类似,作用也一样,不贴代码了
ArrayList$ListItr 内部类
跟AbstractList$ListItr类似,作用也一样,不贴代码了
ArrayList/SubList ArrayList中非public的类
继承AbstractList
抽象类,实现RandomAccess
接口,构造方法中有fromIndex
和toIndex
入参以便重新设计子集合,该类中把AbstractList
没有实现的方法都具体实现了一下,没有什么特别难理解的地方,就不单独贴出来具体代码
Vector 类
继承AbstractList抽象类,实现List, RandomAccess, Cloneable,Serializable接口
Vector跟ArrayList相比,Vector是线程安全的,所有可用方法都使用了synchronized
进行了修饰
Vector有如下3个属性
1
|
protected Object[] elementData; // Vector跟ArrayList类似,底层也是使用数组实现的
|
Vector(int initialCapacity, int capacityIncrement) 构造方法
根据传入的参数initialCapacity
,初始化等长的Object数组——elementData
,同时设置自动扩容的长度为capacityIncrement
Vector(int initialCapacity) 构造方法
根据传入的参数,初始化等长的Object数组——elementData
,设置自动扩容的长度capacityIncrement
为0
Vector() 构造方法
初始化一个长度为10的Object数组——elementData
,设置自动扩容的长度capacityIncrement
为0
Vector(Collection<? extends E> c) 构造方法
c
集合调用toArray()
方法返回的数组设置到elementData
中,长度设置到elementCount
中
void copyInto(Object[] anArray)
将当前Vector
实例复制到anArray
中
void trimToSize()
把集合的长度缩短至集合elementData.length
,也就是把集合末尾未使用到的位置给移除掉。modCount
要自增一次,modCount
是AbstractList
中的属性,用来记录集合变更的次数
void ensureCapacity(int minCapacity)
对Vector实例进行扩容,以够容纳minCapacity
这么多元素。扩容时会让modCount
自增一次。一下代码跟ArrayList.ensureCapacity(int minCapacity)
类似,唯一不同是Vector
的扩容涉及到capacityIncrement
属性
1
|
private void grow(int minCapacity) {
|
##### void setSize(int newSize)
如果newSize
大于当前数组长度,则扩容,如果小于等于当前长度,则把newSize
之外的数组元素置为null
,再把elementCount
设置为newSize
,相当于缩容
int capacity()
返回elementData.length
,是数组实际长度
int size()
返回elementCount
,是Vector
可容纳元素的数量,即设置的长度
##### boolean isEmpty()
返回elementCount == 0
Enumeration elements()
返回Enumeration
接口的实现类(枚举类),类似于迭代器。在使用上更优先使用Iterator
接口
int indexOf(Object o, int index)
从index
位置开始,查找o
在Vector
实例中所在位置的下标
indexOf(Object o)
和int indexOf(Object o, int index)
方法是重载方法,返回indexOf(o, 0)
contains(Object o)
校验indexOf(o, 0)
方法返回的下标值是否大于0
lastIndexOf(Object o, int index)
从index
到0
的范围内,从后往前查找o
元素所在位置的小标
lastIndexOf(Object o)
返回lastIndexOf(o, elementCount-1)
E elementAt(int index)
返回index
位置的元素
E firstElement()
返回数组中的第一个元素
E lastElement()
返回数组中的最后一个元素,最后元素指的是下标为elementCount - 1
位置的元素
void setElementAt(E obj, int index)
重新设置index
位置的元素为obj
void removeElementAt(int index)
modCount
自增,如果index
非数组中的最后一个元素,则把数组中index
后的元素整体前移一个位置,把index
位置的元素挤掉,然后设置elementCount
自减,设置elementCount
位置的元素为null
void insertElementAt(E obj, int index)
modCount
自增,把elementCount + 1
当做Vector
实例最小长度进行扩容,然后对index
后的元素整体后移一位,再设置index
位置的元素为obj
,最后elementCount
自增
void addElement(E obj)
modCount
自增,把elementCount + 1
当做Vector
实例最小长度进行扩容,设置elementCount
位置的元素为obj
,最后elementCount
自增
boolean removeElement(Object obj)
modCount
自增,调用indexOf(Object o)
方法查找obj
元素的下标,再调用removeElementAt(int index)
方法进行删除
void removeAllElements()
modCount
自增,for
循环elementData
数组,设置数组元素全为null
,最后设置elementCount
为0
Object clone()
调用父类clone()
方法获得一个新Vector
实例v
,设置v
的elementData
为Arrays.copyOf(elementData, elementCount)
,v
的modCount
为0,最终返回v
Object[] toArray()
直接返回Arrays.copyOf(elementData, elementCount)
T[] toArray(T[] a)
暂定解释,这个方法有点没太理清楚
E get(int index)
返回elementData
数组中index
位置的元素,和elementAt(int index)
方法其实是一样的
E set(int index, E element)
和setElementAt(E obj, int index)
方法类似,只不过set(int index, E element)
方法返回index
位置的旧值
boolean add(E e)
和addElement(E obj)
方法类似,只不过add(E e)
会返回true
boolean remove(Object o)
直接调用removeElement(o)
void add(int index, E element)
直接调用insertElementAt(element, index)
E remove(int index)
和removeElementAt(int index)
类似,只不过会返回index
位置的旧值
void clear()
返回removeAllElements()
boolean containsAll(Collection<?> c)
调用父类的containsAll(c)
方法
boolean addAll(Collection<? extends E> c)
modCount
自增,把elementCount + numNew
当做集合最小长度进行扩容,在elementData
数组后接上c.toArray
获取到的集合,elementCount
增加到elementCount + numNew
,最终返回numNew != 0
boolean removeAll(Collection<?> c)
调用父类的removeAll(c)
方法
boolean retainAll(Collection<?> c)
调用父类的retainAll(c)
方法
addAll(int index, Collection<? extends E> c)
modCount
自增,数组扩容,对elementData
从index
位置开始右移,再把c集合的元素放置其中,最后设置elementCount
数量,返回numNew != 0
boolean equals(Object o)
调用父类的equals(o)
方法
int hashCode()
调用父类的hashCode
方法
String toString()
调用父类的toString
方法
List subList(int fromIndex, int toIndex)
使用Collections
工具类的synchronizedList(List<T> list, Object mutex)
方法
1
|
public synchronized List<E> subList(int fromIndex, int toIndex) {
|
void removeRange(int fromIndex, int toIndex)
把elementData
中fromIndex
-toIndex
之间的元素移除,计算新的elementCount
,设置elementData
末尾所有的元素为null
ListIterator listIterator(int index)
返回new ListItr(index)
ListIterator listIterator()
返回new ListItr(0)
Iterator iterator()
返回new Itr()
Vector$Itr 内部类
跟父类的类似,不做解释
Vector$ListItr 内部类
跟父类的类似,不做解释
Stack 类
该类是继承自Vector
类的,所以Vector
类中的方法Stack
都可以使用。该类称之为堆栈类,可以使用堆栈的方法进行操作
E push(E item)
向elementData
的末尾增加一个item
元素,调用addElement(item)
方法实现的,最终返回item
E peek()
获取elementData
中最后一个元素
E pop()
获取elementData
中最后一个元素,并将最后一个元素删去
empty()
返回size() == 0
int search(Object o)
查找o
元素距离elementData
末尾的位置
AbstractSequentialList 抽象类
继承自AbstractList
抽象类,对AbstractList
中的几个抽象方法进行了实现
E get(int index)
使用ListIterator
获取从index
位置开始的迭代器,返回index
位置的元素值
E set(int index, E element)
使用ListIterator
获取从index
位置开始的迭代器,设置当前位置为新值element
,最终返回旧值
void add(int index, E element)
使用ListIterator
获取从index
位置开始的迭代器,在该位置后直接插入element
元素
E remove(int index)
使用ListIterator
获取从index
位置开始的迭代器,对该位置元素进行删除,最后返回该元素值
boolean addAll(int index, Collection<? extends E> c)
使用ListIterator
获取从index
位置开始的迭代器,再获取c
集合对应迭代器,依次往当前集合的index
位置后面加入元素。只要加入了元素,就返回true
Iterator iterator()
返回listIterator()
abstract ListIterator listIterator(int index)
待实现
Deque 接口
继承Queue接口,对Queue接口方法进行补充。一个线性 collection,支持在两端插入和移除元素
1
|
void addFirst(E e);
|
LinkedList 类
继承AbstractSequentialList抽象类,实现List, Deque, Cloneable, Serializable接口。该类中有一下3个属性
1
|
transient int size = 0; // 集合长度
|
LinkedList() 构造函数
空的构造函数
LinkedList(Collection<? extends E> c) 构造函数
把c
集合转为LinkedList
集合
LinkedList$Node 内部类
该内部类定义了LinkedList
中各个元素,Node
中设置有3个属性
1
|
E item; // 当前元素
|
LinkedList中比较重要的几个非public方法
1
|
private void linkFirst(E e) {
|
E getFirst()
获取first
元素,返回first.item
E getLast()
获取last
元素,返回last.item
E removeFirst()
获取first
元素,调用unlinkFirst(f)
方法删去第一个元素
E removeLast()
获取last
元素,调用unlinkLast(l)
方法删去最后一个元素
addFirst(E e)
调用linkFirst(e)
方法在集合头插入元素
void addLast(E e)
调用linkLast(e)
方法在集合尾插入元素
boolean contains(Object o)
返回indexOf(o) != -1
int size()
返回size
boolean add(E e)
调用linkLast(e)
方法在集合尾插入元素,返回true
boolean remove(Object o)
循环遍历集合,找到集合中所有的o
元素,调用unlink(x)
方法进行删除,只要删除不止一个元素,就返回true
boolean addAll(Collection<? extends E> c)
返回addAll(size, c)
,在集合末尾新增c
集合
boolean addAll(int index, Collection<? extends E> c)
先校验index是否合法,需要大于等于零,小于等于size
。c调用toArray()方法获得数组a,如果数组长度等于零,则直接返回false。获取index位置的Node为succ,获取succ.pred的Node为pred。再循环a数组,在循环中Node<E> newNode = new Node<>(pred, e, null)
,如果pred
为空,说明当前集合是空的,所以设置first
为newNode
,如果pred
不为空,则设置pred.next
为newNode
,就是设置上一个Node
中的next
为当前newNode
。循环中最后设置pred
为newNode
,以便于下次循环使用。循环结束后如果succ
为空,意味着原集合为空,则需要设置last
为循环中的最后一个Node
,如果succ
不为空,则设置pred.next
为succ
,succ.prev
为pred
。最后size+numNew
,modCount+1
,并返回true
void clear()
循环当前集合,设置每一个Node中的item
、next
、prev
为空,设置集合中的first
、last
为空,size
为0
,modCount+1
E get(int index)
校验index
合法性,获取index
所在位置的Node
,返回该Node
中的item
set(int index, E element)
校验index
合法性,获取index
所在位置的Node
,获取该Node
的item
为oldVal
,设置该Node
的item
值为element
,最后返回oldVal
void add(int index, E element)
校验index
合法性,如果index
为集合末尾,则调用linkLast(element)
增加元素,如果index
非集合末尾,则调用linkBefore(element, node(index))
插入元素
E remove(int index)
校验index
合法性,调用unlink(node(index))
方法删除元素
int indexOf(Object o)
从前往后循环当前集合,返回o
出现的第一个位置的下标,如果没找到则返回-1
int lastIndexOf(Object o)
从后往前循环当前集合,返回o
出现的第一个位置的下标,如果没找到则返回-1
E peek()
获取first
的Node
为f
,如果f
为空,则返回null
,否则返回f.item
E element()
返回getFirst()
方法的结果
E poll()
获取first
的Node
为f
,如果f
为空,则返回null
,否则返回unlinkFirst(f)
方法的结果,相当于返回第一个元素并删去第一个元素
E remove()
返回removeFirst()
方法的结果
boolean offer(E e)
返回add(e)
boolean offerFirst(E e)
调用addFirst(e)
方法,然后返回true
boolean offerLast(E e)
调用addLast(e)
方法,然后返回true
E peekFirst()
获取first
的Node
为f
,如果f
为空,则返回null
,否则返回f.item
E peekLast()
获取last的
Node为
l,如果
l为空,则返回
null,否则返回
l.item`
E pollFirst()
获取first
的Node
为f
,如果f
为空,则返回null
,否则返回unlinkFirst(f)
E pollLast()
获取last的
Node为
l,如果
l为空,则返回
null,否则返回
unlinkLast(l)`
void push(E e)
调用addFirst(e)
方法
E pop()
调用removeFirst()
方法
boolean removeFirstOccurrence(Object o)
调用remove(o)
方法
boolean removeLastOccurrence(Object o)
从后往前遍历集合,在集合中查找o
元素第一次出现对应的Node
为x
,对x
调用unlink(x)
方法进行删除,并返回true
,如果没找到o
元素,则返回false
ListIterator listIterator(int index)
先校验index
的合法性,然后返回new ListItr(index)
迭代器
LinkedList$ListItr 内部类
跟其他集合的ListItr内部类类似
LinkedList$DescendingIterator内部类
跟ListItr
相比,该内部类是一个反序的Iterator
,该类中有一个属性ListItr itr = new ListItr(size())
,类中的hasNext()
方法返回的是itr.hasPrevious()
Object clone()
实现浅克隆,设置克隆的LinkedList
的fisrt = last = null
,size = 0
,modCount = 0
,然后循环当前集合,依次调用add
方法加入到克隆集合中,最后返回
Object[] toArray()
新建一个数组,长度为size
,循环当前集合Node
为x
,数组中依次新增x.item
,最后返回该数组
T[] toArray(T[] a)
暂定解释,这个方法有点没太理清楚
Queue 接口
继承Collection
接口,提供跟队列相关的抽象方法
1
|
boolean add(E e);
|
AbstractQueue 抽象类
继承AbstractCollection
抽象类,实现Queue
接口,该类中对方法的实现都比较抽象,一般都需要具体的类对方法进行重新
boolean add(E e)
如果调用offer(e)
方法返回true
,则该方法返回true
,否则抛异常
E remove()
调用poll()
方法返回对象x
,如果x
不为null
,则返回x
,否则抛异常
E element()
调用peek()
方法返回对象x
,如果x
不为null
,则返回x
,否则抛异常
void clear()
不好描述,直接看代码吧
1
|
public void clear() {
|
boolean addAll(Collection<? extends E> c)
如果c
为null
,抛异常,如果c==this
,抛异常,然后循环c
,调用add(e)
方法进行插入,最终返回集合是否新增了c
PriorityQueue 类
优先级队列,继承AbstractQueue
抽象类,实现Serializable
接口,该集合的实现是以完全二叉树的形式进行存储的
以下是该类中的部分属性
1
|
private static final int DEFAULT_INITIAL_CAPACITY = 11; // PriorityQueue类默认自增长度
|
先列一下该类中的私有方法,因为构造方法中也很可能用到这些私有方法
1
|
// 如果c集合是PriorityQueue类的子类的话,通过该类进行初始化 |