集合框架学习(持续更新)

Java集合框架总体结构图

Collection 接口

定义集合基本方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
boolean add(E e);
boolean remove(Object o);
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c);
void clear();
boolean equals(Object o);
int hashCode();

 

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
boolean add(E e);
boolean remove(Object o);
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean addAll(int index, Collection<? extends E> c);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c);
void clear();
boolean equals(Object o);
int hashCode();
E get(int index);
E set(int index, E element);
void add(int index, E element);
E remove(int index);
int indexOf(Object o);
int lastIndexOf(Object o);
ListIterator<E> listIterator();
ListIterator<E> listIterator(int index);
List<E> subList(int fromIndex, int toIndex);

 

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
2
3
4
5
6
public int hashCode() {
int hashCode = 1;
for (E e : this)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
return hashCode;
}

 

AbstractList$Itr 内部类

直接贴代码介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
private class Itr implements Iterator<E> {
int cursor = 0; // 下一个元素的索引位置
int lastRet = -1; // 上一个元素的索引位置
int expectedModCount = modCount; //modCount是存在AbstractList中的,记录集合修改次数

// 判断是否有下一个元素
public boolean hasNext() {
return cursor != size();
}

//next方法执行完毕之后,当前下标要向后移动一位
public E next() {
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}

//remove操作之后,cursor下标要向前移动一位,因为是做删除操作,所以lastRet重置为-1
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();

try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}

// 判断集合的修改次数是否合法,即用来判断遍历过程中集合是否被修改过
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}

 

AbstractList$ListItr 内部类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// 可以指定从集合中哪个位置开始的迭代器
private class ListItr extends Itr implements ListIterator<E> {
// 构造方法,设置下一个元素的下标为index
ListItr(int index) {
cursor = index;
}

// 判断是否有前一个元素,即只要不是集合中的第一个元素,都会有前一个元素
public boolean hasPrevious() {
return cursor != 0;
}

// 获取当前元素的前一个元素,
public E previous() {
checkForComodification();
try {
int i = cursor - 1;
E previous = get(i);
lastRet = cursor = i;
return previous;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}

// 获取当前元素下一个元素的下标
public int nextIndex() {
return cursor;
}

// 获取当前元素前一个元素的下标
public int previousIndex() {
return cursor-1;
}

// 在当前元素位置,替换成元素e
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();

try {
AbstractList.this.set(lastRet, e);
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}

// 在当前元素后面增加一个元素
public void add(E e) {
checkForComodification();

try {
int i = cursor;
AbstractList.this.add(i, e);
lastRet = -1;
cursor = i + 1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
AbstractList/SubList AbstractList中非public的类

继承AbstractList抽象类,构造方法中有fromIndextoIndex入参以便重新设计子集合,该类中把AbstractList没有实现的方法都具体实现了一下,没有什么特别难理解的地方,就不单独贴出来具体代码

AbstractList/RandomAccessSubList AbstractList中非public的类

继承SubList类,实现RandomAccess接口,就重写了一下List<E> subList(int fromIndex, int toIndex)这个方法,返回的子集合是RandomAccessSubList类型

ArrayList 类

继承AbstractList抽象类,实现List,RandomAccess,Cloneable,Serializable接口,该类中有2个属性

1
2
private transient Object[] elementData; //ArrayList的实现方式其实还是用数组的方式进行的
private int size; //集合长度

 

ArrayList(int initialCapacity) 构造方法

根据传入的集合长度,初始化一个等长的elementData

ArrayList() 构造方法

默认初始化一个长度为10的elementData

ArrayList(Collection<? extends E> c) 构造方法

c集合调用toArray()方法返回的数组赋值到elementData中,并获取elementData的长度设置到size

void trimToSize()

把集合的长度缩短至集合elementData.length,也就是把集合末尾未使用到的位置给移除掉。modCount要自增一次,modCountAbstractList中的属性,用来记录集合变更的次数

void ensureCapacity(int minCapacity)

对ArrayList实例进行扩容,以够容纳minCapacity这么多元素。扩容时会让modCount自增一次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //一些 VMs在数组里保留字头,试图分配更大数组时可能导致OutOfMemoryError:被请求数组的size超出VM界限。

private void grow(int minCapacity) {
int oldCapacity = elementData.length; //原数组长度
int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容逻辑是增加原数组长度一半的容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity; //扩容后的长度还不满足需求要求的最小元素数的话,则直接设置为minCapacity
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity); //如果扩容后的长度超过了MAX_ARRAY_SIZE的话,newCapacity最多长只能设置成Integer.MAX_VALUE,也就是2^31-1这么长
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}

// 获取集合能存储的最长长度
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}

 

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
2
3
4
5
6
7
8
public void add(int index, E element) {
rangeCheckForAdd(index); //先校验一遍index是否是大于0小于size

ensureCapacityInternal(size + 1); // 对elementData进行扩容
System.arraycopy(elementData, index, elementData, index + 1, size - index); // 把elementData中从index开始所有的数据往后移动一个位置
elementData[index] = element; //elementData[index]位置赋值为新的元素值
size++; // 集合长度自增1
}
E remove(int index)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public E remove(int index) {
rangeCheck(index); // 先校验一遍index是否小于size

modCount++; //集合修改次数+1
E oldValue = elementData(index); // 保留集合index位置原来的元素

int numMoved = size - index - 1; // 计算需要移动元素的数量
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved); // 把elementData中从index+1开始所有的数据往前移动一个位置,覆盖原index位置的数据
elementData[--size] = null;

return oldValue;
}
boolean remove(Object o)

for循环找到o元素的下标,然后使用remove(int index)类似的逻辑做删除操作

void clear()

modCount++设置集合修改次数+1,然后for循环elementData,依次设置每个元素都为null,最终设置size0

boolean addAll(Collection<? extends E> c)

放上代码更容易理解

1
2
3
4
5
6
7
8
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray(); // 集合调用toArray方法获取对应数组
int numNew = a.length; // 需要新增的长度
ensureCapacityInternal(size + numNew); // 对elementData进行扩容
System.arraycopy(a, 0, elementData, size, numNew); // a数组从0开始到0+numNew的数据,复制到elementData数组从size开始到size+numNew的位置
size += numNew; // size长度增加numNew
return numNew != 0; // 返回elementData是否新增了数据
}

 

boolean addAll(int index, Collection<? extends E> c)

放上代码更容易理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index); // 先校验一遍index是否是大于0小于size

Object[] a = c.toArray(); // 集合调用toArray方法获取对应数组
int numNew = a.length; // 需要新增的长度
ensureCapacityInternal(size + numNew); // 对elementData进行扩容

int numMoved = size - index; // elementData需要移动数量
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew, numMoved); // elementData从index位置开始,后面所有的数据往后移动numMoved个位置,相当于在index后扩展numMoved个数据的位置

System.arraycopy(a, 0, elementData, index, numNew); // a数组从0开始到0+numNew的数据,复制到elementData数组从index开始到index+numNew的位置
size += numNew; // size长度增加numNew
return numNew != 0; // 返回elementData是否新增了数据
}

 

##### boolean removeAll(Collection<?> c)
返回batchRemove(c, false)

boolean retainAll(Collection<?> c)

返回batchRemove(c, true)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r]; //如果complement为false,即为remove操作,则把elementData中不包含在c集合中的元素重新放置在elementData中,由于r必然>=w,所以无需新new一个数组;如果complement为true,即为contain操作,则把elementData中包含在c集合中的元素重新放置在elementData中。
} finally {
if (r != size) { //这个分支判断有待解决
System.arraycopy(elementData, r, elementData, w, size - r);
w += size - r;
}
if (w != size) { //如果处理过的数组是elementData的子数组的话,把elementData中从w开始到size结束位置所有元素重置为null
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w; // modCount要加上elementData变更次数
size = w; // size长度设置为w
modified = true; // 设置modified为true,仅有w!=size的时候才设置,如果w==size的话相当于没有做任何处理
}
}
return modified;
}

 

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)

先校验fromIndextoIndex是否符合规则,然后返回new SubList(this, 0, fromIndex, toIndex)

ArrayList$Itr 内部类

跟AbstractList$Itr类似,作用也一样,不贴代码了

ArrayList$ListItr 内部类

跟AbstractList$ListItr类似,作用也一样,不贴代码了

ArrayList/SubList ArrayList中非public的类

继承AbstractList抽象类,实现RandomAccess接口,构造方法中有fromIndextoIndex入参以便重新设计子集合,该类中把AbstractList没有实现的方法都具体实现了一下,没有什么特别难理解的地方,就不单独贴出来具体代码

Vector 类

继承AbstractList抽象类,实现List, RandomAccess, Cloneable,Serializable接口
Vector跟ArrayList相比,Vector是线程安全的,所有可用方法都使用了synchronized进行了修饰
Vector有如下3个属性

1
2
3
protected Object[] elementData; //  Vector跟ArrayList类似,底层也是使用数组实现的
protected int elementCount; // Vector实例的长度
protected int capacityIncrement; // 自动扩容时,扩容的长度

 

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要自增一次,modCountAbstractList中的属性,用来记录集合变更的次数

void ensureCapacity(int minCapacity)

对Vector实例进行扩容,以够容纳minCapacity这么多元素。扩容时会让modCount自增一次。一下代码跟ArrayList.ensureCapacity(int minCapacity)类似,唯一不同是Vector的扩容涉及到capacityIncrement属性

1
2
3
4
5
6
7
8
9
10
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity); //如果capacityIncrement大于0,则扩容capacityIncrement长度,如果capacityIncrement不大于0,则扩容原长度的一半
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}

 

##### 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位置开始,查找oVector实例中所在位置的下标

indexOf(Object o)

int indexOf(Object o, int index)方法是重载方法,返回indexOf(o, 0)

contains(Object o)

校验indexOf(o, 0)方法返回的下标值是否大于0

lastIndexOf(Object o, int index)

index0的范围内,从后往前查找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,设置velementDataArrays.copyOf(elementData, elementCount)vmodCount为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自增,数组扩容,对elementDataindex位置开始右移,再把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
2
3
public synchronized List<E> subList(int fromIndex, int toIndex) {
return Collections.synchronizedList(super.subList(fromIndex, toIndex), this);
}

 

void removeRange(int fromIndex, int toIndex)

elementDatafromIndex-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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void addFirst(E e);
void addLast(E e);
boolean offerFirst(E e);
boolean offerLast(E e);
E removeFirst();
E removeLast();
E pollFirst();
E pollLast();
E getFirst();
E getLast();
E peekFirst();
E peekLast();
boolean removeFirstOccurrence(Object o);
boolean removeLastOccurrence(Object o);
// *** Queue methods ***
boolean add(E e);
boolean offer(E e);
E remove();
E poll();
E element();
E peek();
// *** Stack methods ***
void push(E e);
E pop();
// *** Collection methods ***
boolean remove(Object o);
boolean contains(Object o);
public int size();
Iterator<E> iterator();
Iterator<E> descendingIterator();

 

LinkedList 类

继承AbstractSequentialList抽象类,实现List, Deque, Cloneable, Serializable接口。该类中有一下3个属性

1
2
3
transient int size = 0; // 集合长度
transient Node<E> first; // 集合中第一个元素
transient Node<E> last; // 集合中最后一个元素

 

LinkedList() 构造函数

空的构造函数

LinkedList(Collection<? extends E> c) 构造函数

c集合转为LinkedList集合

LinkedList$Node 内部类

该内部类定义了LinkedList中各个元素,Node中设置有3个属性

1
2
3
E item; // 当前元素
Node<E> next; // 集合中当前元素的下一个元素
Node<E> prev; // 集合中当前元素的上一个元素

 

LinkedList中比较重要的几个非public方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
private void linkFirst(E e) {
final Node<E> f = first; // 获取原fisrt的Node为f
final Node<E> newNode = new Node<>(null, e, f); // 构造新Node链到f之前
first = newNode; // 设置first为newNode
if (f == null)
last = newNode; // 如果f为空,意味着集合中没有数据,则first和last都要设置为newNode
else
f.prev = newNode; // 如果f不为空,则f需要移动到第二个位置,相当于设置f.prev为newNode
size++; // 长度+1
modCount++; // 集合修改次数+1
}

void linkLast(E e) {
final Node<E> l = last; // 获取原last的Node为l
final Node<E> newNode = new Node<>(l, e, null); // 构造新Node链到l之后
last = newNode; // 设置last为newNode
if (l == null)
first = newNode; // 如果l为空,意味着集合中没有数据,则first和last都要设置为newNode
else
l.next = newNode; // 如果l不为空,则l需要往前移动一个位置,相当于设置l.next为newNode
size++; // 长度+1
modCount++; // 集合修改次数+1
}

// 在succ之前添加e元素
void linkBefore(E e, Node<E> succ) {
final Node<E> pred = succ.prev; // 获取succ.prev为pred
final Node<E> newNode = new Node<>(pred, e, succ); // 创建Node,把e放置在pred和succ之间
succ.prev = newNode; // succ.prev设置为newNode
if (pred == null)
first = newNode; // 如果pred为空,意味着succ为第一个元素,所以在succ之前加e元素的话,e元素封装的newNode就成为了first
else
pred.next = newNode; 如果pred不为空,则需要设置pred.next为newNode
size++; // 长度+1
modCount++; // 集合修改次数+1
}

// 移除集合中的第一个元素,f必须为first
private E unlinkFirst(Node<E> f) {
final E element = f.item; // first.item
final Node<E> next = f.next; // 获取first.next
f.item = null; // 清空f.item
f.next = null; // 清空f.next = null(利于GC回收)
first = next; // first需要设置为f中的next
if (next == null)
last = null; // 如果next为空,意味着集合为空,则需要设置last也为空
else
next.prev = null; // 如果next不为空,next成为了第一个Node,所以next.prev需要清空
size--; // 长度-1
modCount++; // 修改次数+1
return element;
}

// 移除集合中的最后一个元素,l必须为last,代码逻辑跟unlinkFirst类似,只不过是反操作
private E unlinkLast(Node<E> l) {
final E element = l.item;
final Node<E> prev = l.prev;
l.item = null;
l.prev = null;
last = prev;
if (prev == null)
first = null;
else
prev.next = null;
size--;
modCount++;
return element;
}

// 把x的Node从集合中删去
E unlink(Node<E> x) {
final E element = x.item; // x的元素
final Node<E> next = x.next; // x下一个Node
final Node<E> prev = x.prev; // x上一个Node

if (prev == null) {
first = next; // 如果prev为空,说明x是第一个元素,所以需要重新设置first为next
} else {
prev.next = next; // 如果prev不为空,则需要把prev和next链起来
x.prev = null; // x.prev设置为null
}

if (next == null) {
last = prev; // 如果last为空,说明x是最后一个元素,需要重新设置last为prev
} else {
next.prev = prev; // 如果next不为空,需要把next和prev链起来
x.next = null; // x.next设置为null
}

x.item = null; // x.item设置为null
size--; // 长度-1
modCount++; // 修改次数+1
return element;
}
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为空,说明当前集合是空的,所以设置firstnewNode,如果pred不为空,则设置pred.nextnewNode,就是设置上一个Node中的next为当前newNode。循环中最后设置prednewNode,以便于下次循环使用。循环结束后如果succ为空,意味着原集合为空,则需要设置last为循环中的最后一个Node,如果succ不为空,则设置pred.nextsuccsucc.prevpred。最后size+numNewmodCount+1,并返回true

void clear()

循环当前集合,设置每一个Node中的itemnextprev为空,设置集合中的firstlast为空,size0modCount+1

E get(int index)

校验index合法性,获取index所在位置的Node,返回该Node中的item

set(int index, E element)

校验index合法性,获取index所在位置的Node,获取该NodeitemoldVal,设置该Nodeitem值为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()

获取firstNodef,如果f为空,则返回null,否则返回f.item

E element()

返回getFirst()方法的结果

E poll()

获取firstNodef,如果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()

获取firstNodef,如果f为空,则返回null,否则返回f.item

E peekLast()

获取lastNodel,如果l为空,则返回null,否则返回l.item`

E pollFirst()

获取firstNodef,如果f为空,则返回null,否则返回unlinkFirst(f)

E pollLast()

获取lastNodel,如果l为空,则返回null,否则返回unlinkLast(l)`

void push(E e)

调用addFirst(e)方法

E pop()

调用removeFirst()方法

boolean removeFirstOccurrence(Object o)

调用remove(o)方法

boolean removeLastOccurrence(Object o)

从后往前遍历集合,在集合中查找o元素第一次出现对应的Nodex,对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()

实现浅克隆,设置克隆的LinkedListfisrt = last = nullsize = 0modCount = 0,然后循环当前集合,依次调用add方法加入到克隆集合中,最后返回

Object[] toArray()

新建一个数组,长度为size,循环当前集合Nodex,数组中依次新增x.item,最后返回该数组

T[] toArray(T[] a)

暂定解释,这个方法有点没太理清楚

Queue 接口

继承Collection接口,提供跟队列相关的抽象方法

1
2
3
4
5
6
boolean add(E e);
boolean offer(E e);
E remove();
E poll();
E element();
E peek();

 

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
2
3
4
public void clear() {
while (poll() != null)
;
}

 

boolean addAll(Collection<? extends E> c)

如果cnull,抛异常,如果c==this,抛异常,然后循环c,调用add(e)方法进行插入,最终返回集合是否新增了c

PriorityQueue 类

优先级队列,继承AbstractQueue抽象类,实现Serializable接口,该集合的实现是以完全二叉树的形式进行存储的
以下是该类中的部分属性

1
2
3
4
5
private static final int DEFAULT_INITIAL_CAPACITY = 11; // PriorityQueue类默认自增长度
private transient Object[] queue; // 用数组来实现集合的存储
private int size = 0; // 集合长度
private final Comparator<? super E> comparator; //排序器, 集合中数据按照comparator进行排序
private transient int modCount = 0; // 集合修改次数

 

先列一下该类中的私有方法,因为构造方法中也很可能用到这些私有方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// 如果c集合是PriorityQueue类的子类的话,通过该类进行初始化
private void initFromPriorityQueue(PriorityQueue<? extends E> c) {
if (c.getClass() == PriorityQueue.class) { // 如果c集合类型就是PriorityQueue的话,通过该方法进行初始化(如果c集合类型是PriorityQueue子类是走else的)
this.queue = c.toArray();
this.size = c.size();
} else {
initFromCollection(c); // initFromCollection方法具体介绍
}
}

// 如果c集合仅仅是Collection大类的子类,通过该类进行初始化,能进入该方法的c一般是已排序的集合,或者是调用该方法后另外再排序,所以该方法中没有涉及排序相关操作
private void initElementsFromCollection(Collection<? extends E> c) {
Object[] a = c.toArray(); // 先调用toArray()方法获取数组
if (a.getClass() != Object[].class)
a = Arrays.copyOf(a, a.length, Object[].class); //如果调用toArray()方法获取的数组类型非Object(就算是Object的子类,也要进这个判断),需要创建一个等长的Object类型的数组
int len = a.length; // 获取a数组长度
if (len == 1 || this.comparator != null)
for (int i = 0; i < len; i++)
if (a[i] == null) // PriorityQueue类要求元素不能为null
throw new NullPointerException();
this.queue = a; // 把a数组赋值到queue
this.size = a.length; // 把a数组长度赋值到size
}

// c集合类型非要求的类型,通过该方法来初始化,一般是未排序的集合需要通过该类进行初始化
private void initFromCollection(Collection<? extends E> c) {
initElementsFromCollection(c); // 初始化未排序的数据
heapify(); // 对数据进行排序
}

// 从前往后查找数组是否有o元素,如果有则返回下标,否则返回-1
private int indexOf(Object o) {
if (o != null) {
for (int i = 0; i < size; i++)
if (o.equals(queue[i]))
return i;
}
return -1;
}

// 对集合进行扩容
private void grow(int minCapacity) {
int oldCapacity = queue.length; // 获取集合之前的长度
int newCapacity = oldCapacity + ((oldCapacity < 64) ? (oldCapacity + 2) : (oldCapacity >> 1)); // 如果之前集合长度小于64,则扩展一倍+2,否则扩展原长度的一半
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity); // 如果新数组长度超过MAX_ARRAY_SIZE,需要重置长度,最大不能大于Integer.MAX_VALUE
queue = Arrays.copyOf(queue, newCapacity); 对queue进行扩容
}

private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}

删除i所在位置的元素
private E removeAt(int i) {
assert i >= 0 && i < size; // 使用“断言”来校验i必须大于等于0,小于size
modCount++;
int s = --size; // size先自减1然后再赋值到s
if (s == i)
queue[i] = null; 如果i是最后一个元素,则直接设置queue中最后一个元素为null,利于GC回收
else {
E moved = (E) queue[s]; // 先获取集合中最后一个元素
queue[s] = null; // 设置queue中最后一个元素为null
siftDown(i, moved); // 用末尾元素替换i位置的元素,并将该元素向下沉淀(保证二叉树的有序,即任意节点都是以它为根节点的子树中的最小节点)
if (queue[i] == moved) {
siftUp(i, moved); // 如果向下沉淀没有进行移动,说明该元素有可能需要向上冒泡(保证二叉树的有序,即任意节点都是以它为根节点的子树中的最小节点),所以调用siftUp(i, moved)方法向上比较
if (queue[i] != moved)
return moved; // 如果i位置元素发生变化,说明二叉树结构已经生成,完全二叉树满足条件,如果现在i位置元素还没发生变化,说明moved元素就该在i位置
}
}
return null; // 该方法返回的是移动了的元素,如果i位置刚好需要放置moved元素,则相当于没有移动,所以返回null
}

// 把x元素从k位置开始向上调整以保证二叉树的有序
private void siftUp(int k, E x) {
if (comparator != null)
siftUpUsingComparator(k, x);
else
siftUpComparable(k, x);
}

// 使用默认比较器进行向上调整
private void siftUpComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>) x; // x类强转为Comparable比较器接口的实现类(至于为什么能够进行强转,还不知道)
while (k > 0) {
int parent = (k - 1) >>> 1; // 获取k位置的父节点(完全二叉树的定义)
Object e = queue[parent]; // 获取父节点元素
if (key.compareTo((E) e) >= 0) // 父节点和key进行比较判断是否需要换位置
break;
queue[k] = e; // 如果需要交换,则把e放置在父节点的位置
k = parent; // 然后把父节点原来的值赋值到k,避免丢失
}
queue[k] = key; // 最后把key放置在k位置(k索引在while循环中一直在变)
}

// 跟siftUpComparable(int k, E x)方法类似,只是使用了传入的比较器
private void siftUpUsingComparator(int k, E x) {
while (k > 0) {
int parent = (k - 1) >>> 1;
Object e = queue[parent];
if (comparator.compare(x, (E) e) >= 0)
break;
queue[k] = e;
k = parent;
}
queue[k] = x;
}

// 把x元素从k位置开始向下调整以保证二叉树的有序
private void siftDown(int k, E x) {
if (comparator != null)
siftDownUsingComparator(k, x);
else
siftDownComparable(k, x);
}

// 使用默认比较器进行向下调整
private void siftDownComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>)x;
int half = size >>> 1; // loop while a non-leaf
while (k < half) {
int child = (k << 1) + 1; // 获取k位置的左孩子的下标
Object c = queue[child]; // 获取左孩子的值
int right = child + 1; // 获取k位置的右孩子的下标
if (right < size && ((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
c = queue[child = right]; // 如果右孩子下标未越界,并且左右孩子满足比较条件,则c赋值为右孩子的值,child赋值为有孩子下标
if (key.compareTo((E) c) <= 0)// 子节点和key进行比较判断是否需要换位置
break;
queue[k] = c;// 如果需要交换,则把c放置在子节点的位置
k = child; // 把子节点的下标赋值到k上
}
queue[k] = key; // 最后把key放置在k位置(k索引在while循环中一直在变)
}

// siftDownComparable(int k, E x)方法类似,只是使用了传入的比较器
private void siftDownUsingComparator(int k, E x) {
int half = size >>> 1;
while (k < half) {
int child = (k << 1) + 1;
Object c = queue[child];
int right = child + 1;
if (right < size &&
comparator.compare((E) c, (E) queue[right]) > 0)
c = queue[child = right];
if (comparator.compare(x, (E) c) <= 0)
break;
queue[k] = c;
k = child;
}
queue[k] = x;
}

// 务必把所有的父节点进行向下调整((size >>> 1) - 1有可能有部分子节点在其中,但必须保证包含所有父节点)
private void heapify() {
for (int i = (size >>> 1) - 1; i >= 0; i--)
siftDown(i, (E) queue[i]);
}

 

PriorityQueue() 构造函数

调用this(DEFAULT_INITIAL_CAPACITY, null),自增长度为默认值11

PriorityQueue(int initialCapacity) 构造函数

调用this(initialCapacity, null) 自增长度为传入值

PriorityQueue(int initialCapacity, Comparator<? super E> comparator) 构造函数

校验initialCapacity不能小于1,然后创建一个initialCapacity长度的数组指向queue,设置排序器为传入comparator

PriorityQueue(Collection<? extends E> c) 构造函数

先判断是否是SortedSet子集,如果是,则先把c的比较器传入comparator,然后调用initElementsFromCollection(ss)直接把数据赋值到queue。再判断是否是PriorityQueue子集,如果是,也先把c的比较器传入comparator,然后调用initFromPriorityQueue(pq)直接把数据赋值到queue。如果以上判断都没通过,则设置comparatornull,再调用initFromCollection(c)对集合c转型为PriorityQueue

PriorityQueue(PriorityQueue<? extends E> c) 构造函数

PriorityQueue(Collection<? extends E> c)类似,只不过只针对PriorityQueue子集的集合初始化

PriorityQueue(SortedSet<? extends E> c) 构造函数

PriorityQueue(Collection<? extends E> c)类似,只不过只针对SortedSet子集的集合初始化

boolean add(E e)

返回offer(e)方法

boolean offer(E e)

先校验e是否为null,如果为null则抛异常,然后modCount+1,如果size大于等于queue.length,则对集合长度进行扩容。设置size+1,如果原本的size0,则直接设置queue[0]e,如果不是则调用siftUp(i, e)从末尾往上调整位置,最后返回true

E peek()

如果size0,返回null,否则返回queue[0]

boolean remove(Object o)

先调用indexOf(o)查找o元素下标,如果为-1,则返回false。否则再调用removeAt(i)方法后返回true

boolean removeEq(Object o)

remove(Object o)类似,只不过该方法查找o元素所在位置是使用==,相当于equals+hashCode,而remove(Object o)使用的是equals方法

boolean contains(Object o)

返回indexOf(o) != -1

Object[] toArray()

返回Arrays.copyOf(queue, size)

T[] toArray(T[] a)

暂定解释,这个方法有点没太理清楚

Iterator iterator()

返回new Itr()

int size()

返回size

void clear()

modCount+1,循环queue设置每一个元素都为null,最后设置size0

E poll()

如果size``为0,则返回null。否则modCount+1,获取queue[0]result,获取queue[s]x,重置queue[s]null,只要数组不是只有一个元素,则调用siftDown(0, x)x进行向下调整。最终返回result

Comparator<? super E> comparator()

返回comparator

PriorityQueue$Itr 内部类

跟其他集合的Itr功能类似,只不过因为该类是一个优先级队列所以会有一些特殊处理,只不过所拥有的方法还是那几个没有变,这些方法所实现的功能也没有变,所以这里就不列出来了

Map 接口

定义一种<key, value>这样的键值对,这种键值对是用Entry<K,V>类来实现的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Query Operations
int size();
boolean isEmpty();
boolean containsKey(Object key);
boolean containsValue(Object value);
V get(Object key);
// Modification Operations
V put(K key, V value);
V remove(Object key);
// Bulk Operations
void clear();
// Views
Set<K> keySet();
Collection<V> values();
Set<Map.Entry<K, V>> entrySet();

interface Entry<K,V> {
K getKey();
V getValue();
V setValue(V value);
boolean equals(Object o);
int hashCode();
}

// Comparison and hashing
boolean equals(Object o);
int hashCode();

 

AbstractMap 抽象类

实现Map接口,对Map定义的部分方法进行实现

1
public abstract Set<Entry<K,V>> entrySet(); //该类中的抽象方法,由子类实现。Map中各个元素就是Entry<K,V>,而这些元素的集合就是Set<Entry<K,V>>。在List中各个元素的集合是elementData,而在Map中,是需要调用entrySet()方法来获取Map存储元素的集合

 

int size()

返回entrySet().size()

boolean isEmpty()

返回size() == 0

boolean containsValue(Object value)

获取entrySet()的迭代器,对Map进行迭代,在迭代器循环中Entry<K,V> e = i.next()获取Map中某个元素,再通过e.getValue()判断是否和o相等,相等则返回true,否则返回false

boolean containsKey(Object key)

containsValue(Object value)类似,只不过是通过e.getKey()判断是否和o相等

V get(Object key)

获取entrySet()的迭代器,对Map进行迭代,在迭代器循环中Entry<K,V> e = i.next()获取Map中某个元素,如果e.getKey()等于key,则返回e.getValue()

V put(K key, V value)

默认抛异常,需要实现类重写

V remove(Object key)

获取entrySet()的迭代器,对Map进行迭代,在迭代器循环中Entry<K,V> e = i.next()获取Map中某个元素,如果e.getKey()等于key,把e赋值到之前声明的Entry<K,V> correctEntry中,循环结束使用迭代器i对该元素进行删除,并返回旧值,也就是correctEntry.getValue()。由于使用迭代器前用了while循环,所以找到满足e.getKey()等于key之后,迭代器就停在一个位置了,所以删除时可以继续使用i.remove()

void putAll(Map<? extends K, ? extends V> m)

for循环m.entrySet(),依次调用put(e.getKey(), e.getValue())方法

void clear()

调用entrySet().clear()

Set keySet()

返回一个keySet集合,因为Mapkey不能重复,其实是new了一个AbstractSet<K>,并重新实现了一遍抽象方法

Collection values()

返回一个valueCollection集合,因为Mapvalue可以重复。其实是new了一个AbstractCollection<V>,并重新实现了一遍抽象方法

boolean equals(Object o)

先判断o == this,如果通过返回true;再判断o是否是Map的实现类,如果不是返回false;再判断长度是否相同,如果不相同返回false;最后使用entrySet()的迭代器,对thisMap进行迭代,校验o对应的Map是否包含thiskeyvalue,只要一次不满足就返回false。抛异常的话也返回false

int hashCode()

返回获取Map中每一个元素的hashCode()累加后返回

String toString()

构造字符串并返回

AbstractMap$SimpleEntry 内部类

实现EntrySerializable接口

1
2
private final K key; // key
private V value; // value

 

其他的都是重写了Entry接口中定义的抽象方法

AbstractMap$SimpleImmutableEntry 内部类

不可变的SimpleEntry
AbstractMap$SimpleEntry几乎一样,就是重写的setValue(V value)方法直接抛异常,因为该类不允许变化

HashMap 类

继承AbstractMap抽象类,实现MapCloneableSerializable接口
该类中有以下几个属性

1
2
3
4
5
6
7
8
static final int DEFAULT_INITIAL_CAPACITY = 16; // 默认Map初始化长度
static final int MAXIMUM_CAPACITY = 1 << 30; // Map最大长度
static final float DEFAULT_LOAD_FACTOR = 0.75f; // 默认加载因子
transient Entry[] table; // HashMap外层通过数组来存储
transient int size; // Map长度
int threshold; // 该值是(capacity * load factor),当Map达到这个值时Map进行扩容
final float loadFactor; // 加载因子
transient int modCount; // 修改次数

 

HashMap(int initialCapacity, float loadFactor) 构造方法

校验initialCapacity,如果小于0,则抛异常,如果大于MAXIMUM_CAPACITY则设置initialCapacity = MAXIMUM_CAPACITY。校验loadFactor如果小于等于0或者不是Float类型,抛异常。创建一个capacity = 1,循环左移一位直到大于等initialCapacity。设置loadFactor为传入的loadFactorthreshold(int)(capacity * loadFactor)tablenew Entry[capacity],最后调用init()方法结束

HashMap(int initialCapacity) 构造方法

调用this(initialCapacity, DEFAULT_LOAD_FACTOR),构造因子使用默认值

HashMap() 构造方法

使用默认初始化长度和构造因子构造HashMap

HashMap(Map<? extends K, ? extends V> m) 构造方法
1
2
3
4
5
public HashMap(Map<? extends K, ? extends V> m) {
this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR); // 用m.size() / DEFAULT_LOAD_FACTOR) + 1计算初始化长度,如果该值小于16,则使用16。构造因子使用默认值
putAllForCreate(m); // 把m添加到当前HashMap中
}

static int hash(int h)

直接上代码吧,我看着晕

1
2
3
4
static int hash(int h) {
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}

 

static int indexFor(int h, int length)

也直接上代码吧

1
2
3
static int indexFor(int h, int length) {
return h & (length-1);
}

 

以上2个方法比较关键,另外写了一篇博文HashMap的Hash算法

HashMap$Entry 内部类

实现Map.Entry接口,重写接口中所有的方法,这里不深入讨论具体方法是如何实现的,主要讲一下这个内部类是干嘛用的,具体有哪些属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
final K key; // 用来存Map元素的key值
V value; // 用来存Map元素的value值,跟key是一一对应的
Entry<K,V> next; // 由于HashMap外部是由数组实现,数组中的元素是链表方式存储,所以这里的next是存储当前Entry下一个Entry的
final int hash; // 当前key调用hash(key)方法计算出来的hashCode

/**
* Creates new entry.
*/
Entry(int h, K k, V v, Entry<K,V> n) { // 新增Entry的时候,不用默认构造函数,而是使用有参的构造函数,需要赋值该内部类中的属性
value = v;
next = n;
key = k;
hash = h;
}

 

##### int size()
返回size

boolean isEmpty()

返回size == 0

V get(Object key)
1
2
3
4
5
6
7
8
9
10
11
12
13
public V get(Object key) {
if (key == null) // 先判断key是否为null,如果是null,则返回`getForNullKey()`方法所得
return getForNullKey(); // 该方法也是循环遍历table查找key为null的Entry,返回value
int hash = hash(key.hashCode()); // 根据key.hashCode计算hash
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) { // 找到下标对应的数组位置,该位置有可能有多个Entry存放在这里,所以在该位置进行循环
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) // 循环中依次判断e.hash和上面计算出来的hash是否相等,key值是否相等,如果都相等,返回e.value
return e.value;
}
return null;
}
boolean containsKey(Object key)

返回getEntry(key) != null,其中getEntry(key)get(Object key)方法类似,只不过getEntry方法返回的Entry,而get方法返回的Entry.value

V put(K key, V value)

如果key为null,需要校验Map中是否已存了key为null的值,如果已存在,则返回原来的value,如果不存在,modCount+1,然后调用addEntry(0, null, value, 0)插入一条Entry,key为null时默认认为hash为0。如果key不为null,计算key对应的hash,查询原HashMap是否已存在,存在返回原来的value,不存在的话,modCount+1,然后调用addEntry(hash, key, value, i)插入一条Entry。只要HashMap中存在传入的key,则返回旧值,不存在返回null。

addEntry(int hash, K key, V value, int bucketIndex)

该方法未默认访问权限的方法(default),该方法中会获取bucketIndex位置的元素为Entry<K,V> e,然后table[bucketIndex] = new Entry<>(hash, key, value, e),在bucketIndex位置其实是一个链表,在链表的首位把当前的<key,value>键值对插入进来,也就意味着后存的Entry更靠前。返回校验size++ >= threshold是否达到扩容条件,达到条件后调用resize(2 * table.length)进行扩容。HashMap的容量始终是2的幂数倍。扩容时,会重新计算每个元素的hash

resize(int newCapacity)

该方法未默认访问权限的方法(default),该方法执行HashMap扩容操作,在扩容前,会校验现在table数组的长度是否已经是最大长度,如果已经是最大长度,则不再扩容了。其中newCapacity在该方法中没有任何限制,因为一般调用该方法的位置,会对newCapacity进行校验。然后创建一个newCapacity长度的Entry类型数组,再调用transfer(newTable)方法对原table中各个元素重新计算key.hash,这个操作非常耗资源,所以一般使用HashMap时最好创建时就指定合适的长度。transfer(newTable)结束后就可以把newTable赋值给table,并重新计算threshold以便触发下次的扩容操作

##### transfer(Entry[] newTable)
该方法未默认访问权限的方法(default)。循环原HashMap中的所有元素,根据newCapacity重新计算元素需要放置的位置。由于是循环计算每个元素,所以扩容对资源的消耗比较大

void putAll(Map<? extends K, ? extends V> m)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public void putAll(Map<? extends K, ? extends V> m) {
int numKeysToBeAdded = m.size();
if (numKeysToBeAdded == 0) // m长度校验,必须大于0才往后进行,否则没有put的必要
return;

// m的长度如果大于threshold则进行扩容操作,不理解这个判断为什么不用((m.size() + this.size()) > threshold) 来做。按照jdk原本的解释,如果m中的元素在当前HashMap中有过多的存在的话,用(m.size() + this.size())开辟出来的容量就太大了。如果用numKeysToBeAdded的话,最多额外扩容一次而已
if (numKeysToBeAdded > threshold) {
int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
if (targetCapacity > MAXIMUM_CAPACITY)
targetCapacity = MAXIMUM_CAPACITY;
int newCapacity = table.length;
while (newCapacity < targetCapacity)
newCapacity <<= 1;
if (newCapacity > table.length)
resize(newCapacity);
}

// 在当前HashMap中循环put传入m中的元素
for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
put(e.getKey(), e.getValue());
}
V remove(Object key)
1
2
3
4
public V remove(Object key) {
Entry<K,V> e = removeEntryForKey(key); // 调用该方法进行remove操作,返回的是删除的Entry
return (e == null ? null : e.value); // 如果e不为null,则返回删除的Entry.value
}
Entry<k,v> removeEntryForKey(Object key)

根据key先找到table中的位置,然后循环该位置中的Entry,查找key对应的Entry,找到之后解除链表关联。最后返回removeEntry

void clear()

modCount+1,循环table设置每一项都为null,设置size0。即使数组中某个位置有多个Entry链表,由于没有引用,自己会被GC回收

boolean containsValue(Object value)

循环table中的每一个Entry,判断Entry.value跟传入value是否相等,相等则直接返回true

Object clone()

实现浅克隆

HashMap$HashIterator 内部抽象类

实现Iterator接口,功能不变,不详解了

HashMap$ValueIterator 内部类

继承HashMap$HashIterator抽象类,重写了next方法

HashMap$KeyIterator 内部类

继承HashMap$HashIterator抽象类,重写了next方法

HashMap$EntryIterator 内部类

继承HashMap$HashIterator抽象类,重写了next方法

newXxxIterator()

获取相应的迭代器

1
2
3
4
5
6
7
8
9
Iterator<K> newKeyIterator()   {
return new KeyIterator();
}
Iterator<V> newValueIterator() {
return new ValueIterator();
}
Iterator<Map.Entry<K,V>> newEntryIterator() {
return new EntryIterator();
}

 

Set keySet()

返回key的集合

Collection values()

返回value的集合

Set<map.entry<k,v>> entrySet()

返回Entry的集合

LinkedHashMap 类

继承HashMap类,实现Map接口
该类维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。该类主要的不同在于自己重新定义了一下Entry类,使Entry不仅存储当前元素,还存储了beforeafter元素,使Entry也成为链表的一部分,跟LinkedList有点类似

1
2
private transient Entry<K,V> header; // LinkedHashMap中的定义的头元素,非下标为0的元素,是下标为0更靠前的一个元素
private final boolean accessOrder; // 对于访问顺序,为true;对于插入顺序,则为false。默认是false。当为true时,LinkedHashMap每get一次数据,就会把get的数据放置在第一个位置

 

LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) 构造方法

这个构造方法单独列出来,首先调用super(initialCapacity, loadFactor),然后设置accessOrder为传入的值。这个构造方法是唯一一个能够通过传入方式设置accessOrder值的,其他构造方法都默认设置为false

LinkedHashMap(…) 构造方法

LinkedHashMap其他构造方法就不一一列出来了,因为各个重载的构造方法都是以HashMap为基础,设置accessOrderfalse

void init()

该方法未默认访问权限的方法(default),设置header值的

1
2
3
4
void init() {
header = new Entry<>(-1, null, null, null);
header.before = header.after = header;
}

 

void transfer(HashMap.Entry[] newTable)

扩容时,重新计算各个Entry需要放置的位置,跟HashMap同名方法相比,循环的方式变了,LinkedHashMap中只需要对header的链表进行循环即可

boolean containsValue(Object value)

HashMap同名方法相比,循环的方式变了而已

V get(Object key)

HashMap同名方法相比,主要又调用了一下e.recordAccess(this)方法

void clear()

调用super.clear(),然后重置header

LinkedHashMap$LinkedHashIterator 内部抽象类

实现Iterator接口,跟HashMap$HashIterator类似,功能不变,不详解了

LinkedHashMap$ValueIterator 内部类

继承LinkedHashMap$LinkedHashIterator抽象类,重写了next方法

LinkedHashMap$KeyIterator 内部类

继承LinkedHashMap$LinkedHashIterator抽象类,重写了next方法

LinkedHashMap$EntryIterator 内部类

继承LinkedHashMap$LinkedHashIterator抽象类,重写了next方法

newXxxIterator()

获取相应的迭代器

1
2
3
Iterator<K> newKeyIterator()   { return new KeyIterator();   }
Iterator<V> newValueIterator() { return new ValueIterator(); }
Iterator<Map.Entry<K,V>> newEntryIterator() { return new EntryIterator(); }

 

void addEntry(int hash, K key, V value, int bucketIndex)

新增一个Entry的方法,首先调用createEntry(hash, key, value, bucketIndex)创建Entry,然后获取双向链表中的最旧的Entry,调用removeEldestEntry(eldest)判断是否要求删去最旧值,如果返回true,则删除最旧Entry,如果返回false,则校验是否做扩容处理。removeEldestEntry(eldest)方法是需要子类实现的,LinkedHashMap中默认返回false

LinkedHashMap$Entry 内部类

继承HashMap.Entry

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
private static class Entry<K,V> extends HashMap.Entry<K,V> {
Entry<K,V> before, after; // 定义Entry之前和之后元素

// 构造方法就是调用父方法
Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {
super(hash, key, value, next);
}

// 链表中当前元素解除连接,把当前元素前后的2个Entry进行连接
private void remove() {
before.after = after;
after.before = before;
}

// 把当前Entry连接在existingEntry之前
private void addBefore(Entry<K,V> existingEntry) {
after = existingEntry;
before = existingEntry.before;
before.after = this;
after.before = this;
}

// LinkedHashMap中做gei操作时会调用该方法,根据accessOrder校验是否需要把获取的Entry放在双向链表的头
void recordAccess(HashMap<K,V> m) {
LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
if (lm.accessOrder) {
lm.modCount++;
remove();
addBefore(lm.header);
}
}

// LinkedHashMap中做remove操作时会调用该方法,解除该Entry在双向链表中的绑定
void recordRemoval(HashMap<K,V> m) {
remove();
}
}

 

WeakHashMap 类

继承AbstractMap类,实现Map接口,有以下属性,其他的不介绍,跟HashMap的属性都类似,唯一一个是queue介绍一下。该类跟HashMap总体思路是一样的,主要就是多了一个queue,所以不对所有方法进行介绍,对部分觉得重点的方法进行介绍下就行了

1
2
3
4
5
6
7
8
9
private static final int DEFAULT_INITIAL_CAPACITY = 16;
private static final int MAXIMUM_CAPACITY = 1 << 30;
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
Entry<K,V>[] table;
private int size;
private int threshold;
private final float loadFactor;
private final ReferenceQueue<Object> queue = new ReferenceQueue<>(); // 该队列是GC回收的引用队列,根据queue的方法能够轮询出已回收的引用
int modCount;

 

WeakHashMap(…) 构造方法

构造方法不介绍了,跟HashMap都是一样的

void expungeStaleEntries()

私有方法,获取queue中的key队列,依次在table中进行删除。这个方法在好多地方都有直接或者间接的调用,例如get\put\size\resize\remove\containsValue等等,几乎在所有的public的方法中都有所调用

WeakHashMap$Entry 内部类

继承WeakReference类,实现Map.Entry接口
该类和HashMap.Entry类似,只是该类的构造函数中会使用super(key, queue)queue中注册待回收,当GC对当前key对应的引用做了回收之后key没有从队列中清除,可以通过queue的方法查到被回收的弱键,以便于expungeStaleEntries方法在table中清理失效的Entry

IdentityHashMap 类

继承AbstractMap抽象类,实现MapSerializableCloneable接口
只介绍下看源码后跟HashMap的直观区别

int hash(Object x, int length)

计算hashCode的方式有所变化,这里是直接调用System.identityHashCode(x)来计算hashCode,并且这个方法中直接返回x在数组中应该放置的位置

1
2
3
4
private static int hash(Object x, int length) {
int h = System.identityHashCode(x);
return ((h << 1) - (h << 8)) & (length - 1);
}

 

V put(K key, V value)

Map是以<key, value>形式的键值对,只是在IdentityHashMap类中,keyvalue并不是以Entry的形式存在,而且都作为数组中的元素,key放在第i个位置的话,value放在第i+1个位置。另外在IdentityHashMap类中判断两个key是否相等并不是使用equals方法,是使用“==”来校验,所以key只要不是同一个引用,都可以存放在IdentityHashMap类中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public V put(K key, V value) {
Object k = maskNull(key);
Object[] tab = table;
int len = tab.length;
int i = hash(k, len);

Object item;
while ( (item = tab[i]) != null) {
if (item == k) {
V oldValue = (V) tab[i + 1];
tab[i + 1] = value;
return oldValue;
}
i = nextKeyIndex(i, len);
}

modCount++;
tab[i] = k;
tab[i + 1] = value;
if (++size >= threshold)
resize(len);
return null;
}

 

EnumMap 类

继承AbstractMap抽象类,实现SerializableCloneable接口
这个Map是跟EnumMap一起用的,由于几乎没怎么涉及过Enum,所以这EnumMap我也就不太过多关注了

SortedMap 接口

继承Map接口

1
2
3
4
5
6
7
8
9
Comparator<? super K> comparator();
SortedMap<K,V> subMap(K fromKey, K toKey);
SortedMap<K,V> headMap(K toKey);
SortedMap<K,V> tailMap(K fromKey);
K firstKey();
K lastKey();
Set<K> keySet();
Collection<V> values();
Set<Map.Entry<K, V>> entrySet();

 

继承SortedMap接口扩展的 扩展了SortedMap,具有了针对给定搜索目标返回最接近匹配项的导航方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Map.Entry<K,V> lowerEntry(K key);
K lowerKey(K key);
Map.Entry<K,V> floorEntry(K key);
K floorKey(K key);
Map.Entry<K,V> ceilingEntry(K key);
K ceilingKey(K key);
Map.Entry<K,V> higherEntry(K key);
K higherKey(K key);
Map.Entry<K,V> firstEntry();
Map.Entry<K,V> lastEntry();
Map.Entry<K,V> pollFirstEntry();
Map.Entry<K,V> pollLastEntry();
NavigableMap<K,V> descendingMap();
NavigableSet<K> navigableKeySet();
NavigableSet<K> descendingKeySet();
NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive);
NavigableMap<K,V> headMap(K toKey, boolean inclusive);
NavigableMap<K,V> tailMap(K fromKey, boolean inclusive);
SortedMap<K,V> subMap(K fromKey, K toKey);
SortedMap<K,V> headMap(K toKey);
SortedMap<K,V> tailMap(K fromKey);

 

TreeMap 类

继承AbstractMap抽象类,实现NavigableMapCloneableSerializable接口
属性有以下几个

1
2
3
4
private final Comparator<? super K> comparator; // 由于TreeMap是一个有序的Map,所以需要有比较器
private transient Entry<K,V> root = null; // 根元素
private transient int size = 0; // Map长度
private transient int modCount = 0; // 修改次数

 

TreeMap$Entry 内部类

实现Map.Entry接口

1
2
3
4
5
6
K key; // Entry.key
V value; // Entry.value
Entry<K,V> left = null;
Entry<K,V> right = null;
Entry<K,V> parent;
boolean color = BLACK;

 

TreeMap() 构造方法

设置构造器为null

TreeMap(Comparator<? super K> comparator) 构造方法

设置comparator为传入构造器

TreeMap(Map<? extends K, ? extends V> m) 构造方法

设置构造器为null,调用putAll(m)方法新增元素,是循环调用子类的put方法来实现的

TreeMap(SortedMap<k, ?="" extends="" v=""> m) 构造方法

由于mSortedMap的子类,所以设置构造器为m的构造器,然后调用buildFromSorted(m.size(), m.entrySet().iterator(), null, null)进行元素的插入,该方法后续介绍

int size()

返回size

boolean containsKey(Object key)

返回getEntry(key) != null

boolean containsValue(Object value)

for循环Map中的元素,校验每一个Entry.value是否跟value相等,如果有相等的,就返回true

V get(Object key)

调用getEntry(key),如果返回的结果为null,则get方法也返回null,如果不为null,则返回Entry.value

Comparator<? super K> comparator()

返回comparator比较器

K firstKey()

返回key(getFirstEntry()),返回第一个Entry对应的key

K lastKey()

返回key(getLastEntry()),返回最后一个Entry对应的key

void putAll(Map<? extends K, ? extends V> map)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void putAll(Map<? extends K, ? extends V> map) {
int mapSize = map.size();
if (size==0 && mapSize!=0 && map instanceof SortedMap) { // 这个判断仅对构造函数使用,或者说是当前SortedMap为空
Comparator c = ((SortedMap)map).comparator(); // 获取map的构造器
if (c == comparator || (c != null && c.equals(comparator))) { // 当前构造器和map的构造器就是同一个构造器或者实现逻辑相同
++modCount;
try {
buildFromSorted(mapSize, map.entrySet().iterator(), null, null); // 调用该方法新增元素
} catch (java.io.IOException cannotHappen) {
} catch (ClassNotFoundException cannotHappen) {
}
return;
}
}
super.putAll(map); // 父类putAll方法中,会循环调用子类put方法进行元素的插入
}
Entry<k,v> getEntry(Object key)

Set 接口

定义一个不包含重复元素集合的接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Query Operations
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
// Modification Operations
boolean add(E e);
boolean remove(Object o);
// Bulk Operations
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean retainAll(Collection<?> c);
boolean removeAll(Collection<?> c);
void clear();
// Comparison and hashing
boolean equals(Object o);
int hashCode();

 

AbstractSet 抽象类

继承AbstractCollection抽象类,实现Set接口

boolean equals(Object o)

如果o == this则返回true;如果o不是Set的实现类,则返回false;把o强转为Collectiono,如果o.size()和当前类的size()不等,则返回false;最后返回containsAll(c),如果调用该方法时有异常,异常时返回false

int hashCode()

使用迭代器循环当前集合,累加集合中每个元素的hasCode()最后返回

boolean removeAll(Collection<?> c)

直接看代码吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public boolean removeAll(Collection<?> c) {
boolean modified = false;

if (size() > c.size()) { // 如果当前集合元素数量大于c集合元素数量
for (Iterator<?> i = c.iterator(); i.hasNext(); ) // 使用c集合的迭代器
modified |= remove(i.next()); // remove()执行中只要有一次remove成功,则modified = true(a |=b 相当于 a = a|b)
} else {
for (Iterator<?> i = iterator(); i.hasNext(); ) { // 使用当前集合的迭代器
if (c.contains(i.next())) { // 如果c集合包含当前集合的某个元素,对这个元素进行删除操作
i.remove();
modified = true;
}
}
}
return modified; 最终返回是否删除了元素
}

 

HashSet 类

继承AbstractSet抽象类,实现SetCloneableSerializable接口

1
2
private transient HashMap<E,Object> map; // HashSet默认使用Map来实现
private static final Object PRESENT = new Object(); // Map是<key, value>的键值对,HashSet中只有key没有value,所以使用PRESENT默认当做value

 

HashSet() 构造方法

map = new HashMap<>()HashMap默认初始化容量为16,加载因子为0.75

HashSet(Collection<? extends E> c) 构造方法

map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)),使用默认加载因子0.75计算当前集合长度,如果计算出来长度小于16,则使用16当做map的初始化长度。然后调用addAll(c)方法新增元素到当前HashSet集合中

HashSet(int initialCapacity, float loadFactor) 构造方法

map = new HashMap<>(initialCapacity, loadFactor),使用传入的初始化长度和传入的加载因子初始化map

HashSet(int initialCapacity) 构造方法

map = new HashMap<>(initialCapacity),使用传入的初始化长度和默认加载因子初始化map

HashSet(int initialCapacity, float loadFactor, boolean dummy) 构造方法

map = new LinkedHashMap<>(initialCapacity, loadFactor),构造一个LinkedHashMap

Iterator iterator()

返回mapkey值迭代器 map.keySet().iterator()

int size()

返回map.size()

boolean isEmpty()

返回map.isEmpty()

boolean contains(Object o)

返回map.containsKey(o)

boolean add(E e)

返回map.put(e, PRESENT)==null

boolean remove(Object o)

返回map.remove(o)==PRESENT

void clear()

返回map.clear()

Object clone()
1
2
3
4
5
6
7
8
9
public Object clone() {
try {
HashSet<E> newSet = (HashSet<E>) super.clone(); // 调用父类clone方法
newSet.map = (HashMap<E, Object>) map.clone(); newSet.map则是当前集合中的map调用clone方法
return newSet;
} catch (CloneNotSupportedException e) {
throw new InternalError();
}
}

Activiti学习总结
posted @ 2019-07-31 21:24  qxwang  阅读(45)  评论(0)    收藏  举报