您的位置:首页 > 其它

集合框架源码分析三(实现类篇ArrayList,LinkedList,HashMap)

2012-09-04 00:34 846 查看
一。ArrayList,可自动扩充容量的动态数组

public class ArrayList<E> extends AbstractList<E> implements List<E>,

RandomAccess, Cloneable, java.io.Serializable {

private static final long serialVersionUID = 8683452581122892189L;

/**

*

* 所有ArrayList的元素都存储在此对象数组当中

* ArrayList的容量就是此数组的长度

*/

private transient Object[] elementData;

/**

* 实际拥有的元素的数量

*

* @serial

*/

private int size;

/**

* 构造方法一,指定elementData数组初始长度

*/

public ArrayList(int initialCapacity) {

super();

if (initialCapacity < 0)
//小于0则抛出IllegalArgumentException

throw new IllegalArgumentException("Illegal Capacity: "

+ initialCapacity);

this.elementData = new Object[initialCapacity];

}

/**

* 构造方法二,默认elementData数组初始长度为10

*/

public ArrayList() {

this(10);

}

/**

* 构造方法三,构造一个包含指定 collection 的元素的List

*/

public ArrayList(Collection<? extends E> c) {

elementData = c.toArray();
//toArray方法由AbstractCollection实现,返回一个对象数组

size = elementData.length; //元素的顺序是由迭代器迭代顺序决定的,详情见toArray方法实现

// c.toArray might (incorrectly) not return Object[] (see 6260652)

if (elementData.getClass() != Object[].class)
//如果返回的不是一个数组对象

elementData = Arrays.copyOf(elementData, size, Object[].class);

}

/**

* 修剪ArrayList的容量为实际size长度

*/

public void trimToSize() {

modCount++;
//此方法改变了数组结构,需要检测是否同步

int oldCapacity = elementData.length;

if (size < oldCapacity) {

elementData = Arrays.copyOf(elementData, size);

}

}

/**

*

* 扩充数组容量,并指定其最小的容量,即至少容量大小为minCapacity

*/

public void ensureCapacity(int minCapacity) {

modCount++;

int oldCapacity = elementData.length;

if (minCapacity > oldCapacity) {
//指定最小容量比原来容量大才扩充

Object oldData[] = elementData;

int newCapacity = (oldCapacity * 3) / 2 + 1;
//扩充原容量的1.5倍加1

if (newCapacity < minCapacity)
//扩充后还是小于要求的最小容量,则扩充容量为最小容量

newCapacity = minCapacity;

elementData = Arrays.copyOf(elementData, newCapacity);

}

}

/**

* 返回List中的元素个数

*/

public int size() {

return size;

}

/**

* List是否不含元素

*/

public boolean isEmpty() {

return size == 0;

}

/**

* 查看o是否包含在ArrayList中,内部调用了indexOf方法实现

*/

public boolean contains(Object o) {

return indexOf(o) >= 0;

}

/**

* 父类AbstractList的indexOf方法使用的是list迭代器遍历元素

* 这里重写了indexOf方法直接遍历数组即可

* 返回指定元素第一次在数组中出现的索引

* 如果找不到此元素则返回-1

*/

public int indexOf(Object o) {

if (o == null) {

for (int i = 0; i < size; i++)

if (elementData[i] == null)

return i;

} else {

for (int i = 0; i < size; i++)

if (o.equals(elementData[i]))

return i;

}

return -1;

}

/**

* 基本同上

*/

public int lastIndexOf(Object o) {

if (o == null) {

for (int i = size - 1; i >= 0; i--)

if (elementData[i] == null)

return i;

} else {

for (int i = size - 1; i >= 0; i--)

if (o.equals(elementData[i]))

return i;

}

return -1;

}

/**

*

* 返回ArrayList的浅拷贝实例对象,包含所有元素

*/

public Object clone() {

try {

ArrayList<E> v = (ArrayList<E>) super.clone();

v.elementData = Arrays.copyOf(elementData, size);

v.modCount = 0;

return v;

} catch (CloneNotSupportedException e) {
//如果未实现Cloneable则会抛出CloneNotSupportedException

throw new InternalError();

}

}

/**

*

* 返回的对象数组是安全的,因为它是一个全新的对象

* 操作返回的数组并不会影响到ArrayList对象

*

*/

public Object[] toArray() {

return Arrays.copyOf(elementData, size);

}

/**

* 返回一个指定类型的包含List所有元素的数组

*/

public <T> T[] toArray(T[] a) {

if (a.length < size)
//如果a的长度小于List元素个数

return (T[]) Arrays.copyOf(elementData, size, a.getClass());
//以指定类型返回一个新数组,长度为size

System.arraycopy(elementData, 0, a, 0, size);
//否则把elementData中元素复制到a

if (a.length > size)
//如果a的长度大于size则在最后位置加一个null元素,等于的话就不用加了

a[size] = null;
//这对了解它的实际长度很有效

return a;

}

// Positional Access Operations

public E get(int index) {

RangeCheck(index);
//检查是否越界

return (E) elementData[index];
//直接返回数组某位置的元素即可

}

/**

* 对数组指定所有的值进行替换,并返回上一个值

*/

public E set(int index, E element) {

RangeCheck(index);
//检查是否越界

E oldValue = (E) elementData[index];
//so easy

elementData[index] = element;

return oldValue;

}

/**

* 在数组size位置添加一个元素

*

*/

public boolean add(E e) {

ensureCapacity(size + 1); // modCount++,并检查是否需要扩充容量

elementData[size++] = e;
//size++

return true;

}

/**

*

* 在指定位置添加一个元素,当前在此位置的元素以及其后面的元素都要向后移动一个位置

* 此方法的效率较低

*

*/

public void add(int index, E element) {

if (index > size || index < 0)
//检查是否越界

throw new IndexOutOfBoundsException("Index: " + index + ", Size: "

+ size);

ensureCapacity(size + 1); // Increments modCount!!

System.arraycopy(elementData, index, elementData, index + 1, size

- index);
//把原来index位置的元素,复制到index+1的位置,后面的size-index-1长度的元素依次复制

elementData[index] = element;
//空出的index位置的元素设为element

size++;

}

/**

*

* 移除指定位置的元素,其后面的元素都要向左移动一个位置

* 此方法的效率较低

*/

public E remove(int index) {

RangeCheck(index);

modCount++;
//modCount是为了检测是否发生了并发操作,详细见AbstractList类

E oldValue = (E) elementData[index];

int numMoved = size - index - 1;
//与add相比少移一个元素

if (numMoved > 0)
//是否移除的是最后一个元素

System.arraycopy(elementData, index + 1, elementData, index,

numMoved);
//index位置的元素被移除了,原来index+1位置的元素复制到index位置,随后的元素依次复制

elementData[--size] = null; // Let gc do its work,size位置的元素空出来了

return oldValue;

}

/**

*

* 如果o在List中存在,移除第一次出现在List中的o元素

* 如果o在List中不存在,不做任何操作

*

*/

public boolean remove(Object o) {

if (o == null) {

for (int index = 0; index < size; index++)
//直接遍历数组

if (elementData[index] == null) {

fastRemove(index);
//快速移除此元素

return true;

}

} else {

for (int index = 0; index < size; index++)

if (o.equals(elementData[index])) {

fastRemove(index);

return true;

}

}

return false;

}

/*

*

* 与remove(int index)方法差不多,

* 不过不用检测是否越界与返回原来的index位置的值

*/

private void fastRemove(int index) {

modCount++;

int numMoved = size - index - 1;

if (numMoved > 0)

System.arraycopy(elementData, index + 1, elementData, index,

numMoved);

elementData[--size] = null; // Let gc do its work

}

/**

* 移除所有元素,即把所有元素设为null,size=0

*/

public void clear() {

modCount++;

// Let gc do its work

for (int i = 0; i < size; i++)

elementData[i] = null;

size = 0;

}

/**

* 把a中所有元素添加到数组尾部

*/

public boolean addAll(Collection<? extends E> c) {

Object[] a = c.toArray();

int numNew = a.length;

ensureCapacity(size + numNew); // Increments modCount

System.arraycopy(a, 0, elementData, size, numNew); //从size位置开始复制a

size += numNew;
//size增加

return numNew != 0;

}

/**

*

* 在指定位置开始添加指定集合c中的所有元素

* 当前位置及其随后位置的元素后移

*/

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

if (index > size || index < 0)
//检测是否越界

throw new IndexOutOfBoundsException("Index: " + index + ", Size: "

+ size);

Object[] a = c.toArray();

int numNew = a.length;

ensureCapacity(size + numNew); // Increments modCount

int numMoved = size - index;
//移动元素数量

if (numMoved > 0)

System.arraycopy(elementData, index, elementData, index + numNew,

numMoved);
//把原来index位置的元素,复制到index+numNew的位置,后面的size-index-1长度的元素依次复制

System.arraycopy(a, 0, elementData, index, numNew);
//空出来的位置填充c

size += numNew;

return numNew != 0;

}

/**

*

* 移除所有从fromIndex(包含)到toIndex(不包含)范围内的元素,

* 左移随后的元素.如果toIndex=fromIndex,此操作无影响

*

*/

protected void removeRange(int fromIndex, int toIndex) {

modCount++;

int numMoved = size - toIndex;

System.arraycopy(elementData, toIndex, elementData, fromIndex,

numMoved);
//把toIndex位置的元素复制到fromIndex,随后的元素依次复制,总共复制numMoved个元素

// Let gc do its work

int newSize = size - (toIndex - fromIndex);

while (size != newSize)
//这里是为了让gc工作,不直接把size设为newSize

elementData[--size] = null;

}

/**

*

* 这里并没有检测index小于0的情况

* 它总是由数组自己检测,抛出的异常也不同,为ArrayIndexOutOfBoundsException

*/

private void RangeCheck(int index) {

if (index >= size)

throw new IndexOutOfBoundsException("Index: " + index + ", Size: "

+ size);

}

/**

* 序列化ArrayList,保存ArrayList实例状态

* 保存的是数组长度,及其所有元素

*

*/

private void writeObject(java.io.ObjectOutputStream s)

throws java.io.IOException {

// Write out element count, and any hidden stuff

int expectedModCount = modCount;

s.defaultWriteObject();

// 写入数组长度

s.writeInt(elementData.length);

// 按顺序写入所有元素

for (int i = 0; i < size; i++)

s.writeObject(elementData[i]);

if (modCount != expectedModCount) {
//检测到了并发操作

throw new ConcurrentModificationException();

}

}

/**

* Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,

* deserialize it).

*/

private void readObject(java.io.ObjectInputStream s)

throws java.io.IOException, ClassNotFoundException {

// Read in size, and any hidden stuff

s.defaultReadObject();

// 读出数组长度

int arrayLength = s.readInt();

Object[] a = elementData = new Object[arrayLength];
//保存

// 依次读出所有元素

for (int i = 0; i < size; i++)

a[i] = s.readObject();

}

}

二。LikedList(双向循环链表)

public class LinkedList<E> extends AbstractSequentialList<E> implements

List<E>, Deque<E>, Cloneable, java.io.Serializable {

//在第一个节点之前附设的一个节点称为头结点,有元素添加会重设值

//此变量在序列化时不保存

private transient Entry<E> header = new Entry<E>(null, null, null);

private transient int size = 0;
//List存储的Entry对象个数

/**

* 构造方法一,空链表

*/

public LinkedList() {

header.next = header.previous = header;
//只有一个头结点的链表

}

/**

* 构造方法二,构造含有指定集合c中所有元素的链表

* 具体见addAll方法

*/

public LinkedList(Collection<? extends E> c) {

this();

addAll(c);

}

/**

* 获取第一个元素的值,即头结点的下一个元素的数据部分

*/

public E getFirst() {

if (size == 0)

throw new NoSuchElementException();

return header.next.element;

}

/**

* 双向循环链表,你懂得

*/

public E getLast() {

if (size == 0)

throw new NoSuchElementException();

return header.previous.element;

}

/**

* 移除第一个元素,具体见remove()方法

*/

public E removeFirst() {

return remove(header.next);

}

/**

* 移除最后一个元素

*/

public E removeLast() {

return remove(header.previous);

}

/**

*

* 在链表开始位置添加一个元素

* 详情见addBefore()

*/

public void addFirst(E e) {

addBefore(e, header.next);

}

/**

* 在链表最后位置添加一个元素

* 详情见addBefore()

*/

public void addLast(E e) {

addBefore(e, header);

}

/**

* 查看链表是否包含元素o

* 详细见indexOf()方法

*/

public boolean contains(Object o) {

return indexOf(o) != -1;

}

/**

* 链表所含元素的数量

*/

public int size() {

return size;

}

/**

* 跟addLast()方法类似,添加成功返回true

*/

public boolean add(E e) {

addBefore(e, header);

return true;

}

/**

* 假如链表中含有一个或多个o对象,移除第一次出现的o

* 如果找不到o返回false

*/

public boolean remove(Object o) {

if (o == null) {

for (Entry<E> e = header.next; e != header; e = e.next) {
//从第一个元素开始遍历,每一个Entry对象都包含它下一个元素的信息

if (e.element == null) {

remove(e);

return true;

}

}

} else {

for (Entry<E> e = header.next; e != header; e = e.next) {

if (o.equals(e.element)) {

remove(e);

return true;

}

}

}

return false;

}

/**

*

* 把c中所有元素按顺序添加到链表尾部

*/

public boolean addAll(Collection<? extends E> c) {

return addAll(size, c);

}

/**

*

* 在指定位置按顺序添加c中所有元素带List中

*

*/

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

if (index < 0 || index > size)
//检查是否越界,=size表示添加到最后

throw new IndexOutOfBoundsException("Index: " + index + ", Size: "

+ size);

Object[] a = c.toArray();

int numNew = a.length;

if (numNew == 0)

return false;

modCount++;
//对链表结构产生 影响的操作modCount都要加1,通过modCount可以检查是否对链表进行了并发操作

Entry<E> successor = (index == size ? header : entry(index));

Entry<E> predecessor = successor.previous;

for (int i = 0; i < numNew; i++) {
//这里不难,画一个图就出来了,主要是初始化c和修改指针

//暂时使其next为successor,因为e会赋给前驱,而每次遍历都要修改其前驱的next

Entry<E> e = new Entry<E>((E) a[i], successor, predecessor);
//把c中元素依次存入Entry,设置其前驱和后继。

predecessor.next = e; //重新设置前驱的next指针

predecessor = e;
//让e变为前驱

}

successor.previous = predecessor;
//successor的前驱为c中最后一个元素的引用

size += numNew;
//长度加

return true;

}

/**

* 移除链表中所有元素

*/

public void clear() {

Entry<E> e = header.next;

while (e != header) {
//表示不是只有一个头结点的空链表

Entry<E> next = e.next;

e.next = e.previous = null;
//let gc work

e.element = null;

e = next;

}

header.next = header.previous = header;
//初始头结点

size = 0;

modCount++;

}

// Positional Access Operations

/**

* 返回指定位置的元素时

*/

public E get(int index) {

return entry(index).element;

}

/**

* 设置指定位置的元素

*/

public E set(int index, E element) {

Entry<E> e = entry(index);

E oldVal = e.element;

e.element = element;

return oldVal;

}

/**

*

* 把指定元素添加到指定位置,需先定位到此位置的节点

* 详情见addBefore()

*/

public void add(int index, E element) {

addBefore(element, (index == size ? header : entry(index)));

}

/**

* 移除指定位置的元素

*/

public E remove(int index) {

return remove(entry(index));

}

/**

*

* 返回指定索引位置的Entry对象,需要依次遍历得到。

* 这里稍做了一下优化,如果index < size/2 从前面开始遍历

* 如果index >= size/2 从后面开始遍历

*/

private Entry<E> entry(int index) {

if (index < 0 || index >= size)
//index在0(包含)到size(不包含)之间,索引从0开始

throw new IndexOutOfBoundsException("Index: " + index + ", Size: "

+ size);

Entry<E> e = header;

if (index < (size >> 1)) {

for (int i = 0; i <= index; i++)

e = e.next;
//依次调用e.next才能得到,需调用index+1次,因为它是从头结点开始的

} else {

for (int i = size; i > index; i--)

e = e.previous; //依次调用e.previous才能得到

}

return e;

}

// Search Operations

/**

*

* 返回o第一次出现的位置,如果在List中找不到o返回-1

*/

public int indexOf(Object o) {

int index = 0;
//链表的索引也是从0开始

if (o == null) {

for (Entry e = header.next; e != header; e = e.next) {
//从头结点开始,依次遍历

if (e.element == null)

return index;

index++;

}

} else {

for (Entry e = header.next; e != header; e = e.next) {

if (o.equals(e.element))

return index;

index++;

}

}

return -1;

}

/**

* 双向循环链表,从后面开始遍历即可

*/

public int lastIndexOf(Object o) {

int index = size;

if (o == null) {

for (Entry e = header.previous; e != header; e = e.previous) {

index--;

if (e.element == null)

return index;

}

} else {

for (Entry e = header.previous; e != header; e = e.previous) {

index--;

if (o.equals(e.element))

return index;

}

}

return -1;

}

// Queue operations.有关队列的基本操作

/**

* 如果链表长度不为空,获取第一个元素

* 否则返回null

*/

public E peek() {

if (size == 0)

return null;

return getFirst();

}

/**

* 跟peek方法相似,不过这里size为0的话直接抛出异常

*/

public E element() {

return getFirst();

}

/**

* 如果链表长度不为空,移除第一个元素,并返回它

* 否则返回null

*/

public E poll() {

if (size == 0)

return null;

return removeFirst();

}

/**

* 与poll方法类似,不过长度为空,即header.next = header

* 抛出NoSuchElementException

*/

public E remove() {

return removeFirst();

}

/**

* 添加一个元素到链表尾部

*/

public boolean offer(E e) {

return add(e);

}

// Deque operations

/**

* 添加一个元素到头结点之后,原来的第一个节点之前

*/

public boolean offerFirst(E e) {

addFirst(e);

return true;

}

/**

* 在尾部添加一个元素

*/

public boolean offerLast(E e) {

addLast(e);

return true;

}

/**

* 获取第一个元素,如果size为0,返回空

* 否则返回第一个元素

*/

public E peekFirst() {

if (size == 0)

return null;

return getFirst();

}

/**

* 获取最后一个元素,如果size为0,返回空

* 否则返回最后一个元素

*/

public E peekLast() {

if (size == 0)

return null;

return getLast();

}

/**

*

* 移除第一个元素并返回它

* 如果size为0则直接返回null

*/

public E pollFirst() {

if (size == 0)

return null;

return removeFirst();

}

/**

* 移除最后一个元素并返回它

* 如果size为0则直接返回null

*/

public E pollLast() {

if (size == 0)

return null;

return removeLast();

}

/**

* 在开始位置添加一个元素

*/

public void push(E e) {

addFirst(e);

}

/**

* 移除第一个元素

*/

public E pop() {

return removeFirst();

}

/**

*

* 移除第一次出现的指定的元素

* 如果遍历整个List后没有找到o,则不做任何改变

*

*/

public boolean removeFirstOccurrence(Object o) {

return remove(o);

}

/**

* 这个差不多,从后面开始遍历即可

*/

public boolean removeLastOccurrence(Object o) {

if (o == null) {

for (Entry<E> e = header.previous; e != header; e = e.previous) {

if (e.element == null) {

remove(e);

return true;

}

}

} else {

for (Entry<E> e = header.previous; e != header; e = e.previous) {

if (o.equals(e.element)) {

remove(e);

return true;

}

}

}

return false;

}

/**

*

* 返回一个list-iterator.

*/

public ListIterator<E> listIterator(int index) {

return new ListItr(index);

}

/**

* 重新 实现ListIterator,使其跟符合链表的特性

* iterator方法由AbstractSequentialList实现了,

* 但是调用的还是本ListIterator。只不过只能使用iterator接口的方法

* */

private class ListItr implements ListIterator<E> {

private Entry<E> lastReturned = header;
//上一次调用next或previous返回的元素,没有调用next则为头结点

private Entry<E> next;
//下一次调用next方法返回的元素

private int nextIndex;
//下一次调用next返回的元素的索引

private int expectedModCount = modCount;
//用来检测遍历过程中是否产生了并发操作

ListItr(int index) {
//构造器,是迭代器定位到index位置,要返回index位置的元素需调用一次next()方法时

if (index < 0 || index > size)

throw new IndexOutOfBoundsException("Index: " + index

+ ", Size: " + size);

if (index < (size >> 1)) {
//从前面开始遍历

next = header.next;
//这是index为0的元素

for (nextIndex = 0; nextIndex < index; nextIndex++)

next = next.next;
//最终next为第index个元素,index从0开始

} else {
//从后面开始遍历

next = header;

for (nextIndex = size; nextIndex > index; nextIndex--)

next = next.previous;
//最终next为第index个元素,index从0开始

}

}

public boolean hasNext() {
//size位置可没有元素

return nextIndex != size;

}

public E next() {

checkForComodification();

if (nextIndex == size)

throw new NoSuchElementException();

lastReturned = next;

next = next.next;
//这里与ArrayList中的cursor何其相似

nextIndex++;

return lastReturned.element;

}

public boolean hasPrevious() {

return nextIndex != 0;

}

public E previous() {

if (nextIndex == 0)

throw new NoSuchElementException();

lastReturned = next = next.previous;

nextIndex--;

checkForComodification();

return lastReturned.element;

}

public int nextIndex() {
//返回下一次调用next返回的元素的索引

return nextIndex;

}

public int previousIndex() {
//返回下一次调用previous返回的元素的索引

return nextIndex - 1;

}

public void remove() {

checkForComodification();

Entry<E> lastNext = lastReturned.next;

try {

LinkedList.this.remove(lastReturned);
//移除上一层调用next()或previous返回的元素

} catch (NoSuchElementException e) {

throw new IllegalStateException();

}

if (next == lastReturned)
//表明是调用previous后才调用remove方法

next = lastNext;

else

nextIndex--;
//元素减少。nextIndex--

lastReturned = header;
//重置lastReturned

expectedModCount++;

}

public void set(E e) {

if (lastReturned == header)

throw new IllegalStateException();

checkForComodification();

lastReturned.element = e;

}

public void add(E e) {

checkForComodification();

lastReturned = header;

addBefore(e, next);
//在上一次调用next返回的元素之后,在上次调用previous返回的元素之前添加e

nextIndex++;
//元素增加,索引增加,保证下次调用next()不是返回添加的元素

expectedModCount++;

}

final void checkForComodification() {

if (modCount != expectedModCount)

throw new ConcurrentModificationException();

}

}

/**

* LinkedList的元素节点,保存当前节点的元素

* 以及下一个节点,和上一个节点的引用

* 由此看出LinkedList是一个双向链表

*/

private static class Entry<E> {

E element;
//当前节点元素

Entry<E> next;
//下一个节点引用

Entry<E> previous;
//上一个节点引用

Entry(E element, Entry<E> next, Entry<E> previous) {

this.element = element;

this.next = next;

this.previous = previous;

}

}

/**

* 在entry之前添加一个节点e

*

*/

private Entry<E> addBefore(E e, Entry<E> entry) {

Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
//新节点的前驱和后继,只有一个元素的话前驱和后继都为header

newEntry.previous.next = newEntry;
//新节点的前驱的后继为新节点,只包含newEntry一个元素的话修改的是头结点的next

newEntry.next.previous = newEntry;
//新节点的后继的前驱为新节点,只包含newEntry一个元素的话修改的是头结点的previous

size++;

modCount++;

return newEntry;

}

/**

* 移除指定节点

*/

private E remove(Entry<E> e) {

if (e == header)

throw new NoSuchElementException();

E result = e.element;

//修改节点指针

e.previous.next = e.next;
//e的前驱的后继等于e的后继

e.next.previous = e.previous;
//e的后继的前驱等于e的前驱

e.next = e.previous = null;
//let gc work

e.element = null;

size--;
//size--

modCount++;

return result;

}

/**

* 逆序返回所有元素的迭代器

*/

public Iterator<E> descendingIterator() {

return new DescendingIterator();

}

/** Adapter to provide descending iterators via ListItr.previous */

private class DescendingIterator implements Iterator {

final ListItr itr = new ListItr(size());

public boolean hasNext() {

return itr.hasPrevious();

}

public E next() {

return itr.previous();

}

public void remove() {

itr.remove();

}

}

/**

* 返回一个LikedList的浅拷贝对象

*/

public Object clone() {

LinkedList<E> clone = null;

try {

clone = (LinkedList<E>) super.clone();

} catch (CloneNotSupportedException e) {

throw new InternalError();

}

// Put clone into "virgin" state,即重置其为初始状态

clone.header = new Entry<E>(null, null, null);

clone.header.next = clone.header.previous = clone.header;

clone.size = 0;

clone.modCount = 0;

// 初始化克隆对象

for (Entry<E> e = header.next; e != header; e = e.next)

clone.add(e.element);

return clone;

}

/**

* 返回一个新建对象数组,包含链表中所有元素

*/

public Object[] toArray() {

Object[] result = new Object[size];
//新建一size长度对象数组

int i = 0;

for (Entry<E> e = header.next; e != header; e = e.next)
//遍历赋值

result[i++] = e.element;

return result;

}

/**

* 所有toArray方法都是一个思想...

* 只是遍历方式不同

* */

public <T> T[] toArray(T[] a) {

if (a.length < size)
//如果指定数组长度小于size,新建一数组

a = (T[]) java.lang.reflect.Array.newInstance(a.getClass()

.getComponentType(), size);

int i = 0;

Object[] result = a;

for (Entry<E> e = header.next; e != header; e = e.next)

result[i++] = e.element;

if (a.length > size) //同ArrayList

a[size] = null;

return a;

}

private static final long serialVersionUID = 876323262645176354L;

/**

* 序列化LikedList,保存其状态

*/

private void writeObject(java.io.ObjectOutputStream s)

throws java.io.IOException {

// Write out any hidden serialization magic

//添加一些序列化的额外信息,表明它是一个序列化的文件

s.defaultWriteObject();

// 写长度

s.writeInt(size);

// 写元素

for (Entry e = header.next; e != header; e = e.next)

s.writeObject(e.element);

}

/**

* 从流中读取

*/

private void readObject(java.io.ObjectInputStream s)

throws java.io.IOException, ClassNotFoundException {

// Read in any hidden serialization magic

s.defaultReadObject();

// 读长度

int size = s.readInt();

// 初始化header

header = new Entry<E>(null, null, null);

header.next = header.previous = header;

// 按顺序写入所有元素

for (int i = 0; i < size; i++)

addBefore((E) s.readObject(), header);

}

}

三。HashMap(数组加链表的结合体)

/**

* 作用:用于实现快速查找

* HashMap实现的数据结构:动态数组和链表的结合体

* */

public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>,

Cloneable, Serializable {

/**

* 默认初始数组容量,必须为2的幂

*/

static final int DEFAULT_INITIAL_CAPACITY = 16;

/**

*

* 最大容量为1 * 2^30 即2的30次方

*/

static final int MAXIMUM_CAPACITY = 1 << 30;

/**

*

* hashMap的加载系数,当数组中的元素增多时,通过hash函数算出的数组下标

* 相同几率增加。为保证查找的效率,当数组中的元素超过

* load_factor * table.length 时就要扩充容量

* 默认加载系数为0.75

*/

static final float DEFAULT_LOAD_FACTOR = 0.75f;

/**

*

* 数组存放Entry对象,单向链表的第一个元素,

* 通过它可以遍历整个链表。

* table长度会在需要时进行扩充,table长度始终为2的幂

*/

transient Entry[] table;

/**

* key-value键值对个数

*/

transient int size;

/**

* HashMap size >= threshlod时就扩充数组容量

*/

int threshold;

/**

* hash表加载因子

*/

final float loadFactor;

/**

*

* hash表发生结构性改变的次数,这些方法包括,put,remove等对size进行改变的操作

* 用iterator遍历时可以用来检测是否对HashMap进行了并发操作

*/

transient volatile int modCount;

/**

* 根据指定的初始容量和加载系数构建hashMap

* 初始容量如果不是2的幂,会被构造成2的幂

*/

public HashMap(int initialCapacity, float loadFactor) {

if (initialCapacity < 0)

throw new IllegalArgumentException("Illegal initial capacity: "

+ initialCapacity);

if (initialCapacity > MAXIMUM_CAPACITY)

initialCapacity = MAXIMUM_CAPACITY;

if (loadFactor <= 0 || Float.isNaN(loadFactor))

throw new IllegalArgumentException("Illegal load factor: "

+ loadFactor);

//找到一个2的幂的数,使其大于等于初始容量

int capacity = 1;

while (capacity < initialCapacity)

capacity <<= 1;
// capacity = capacity << 1,左移一位

this.loadFactor = loadFactor;

threshold = (int) (capacity * loadFactor);

table = new Entry[capacity];

init();
//所有构造方法都含有此空方法,做一些其他初始化操作。根据业务要求,可由其子类实现

}

/**

* 根据指定容量与默认加载系数构建HashMap

*/

public HashMap(int initialCapacity) {

this(initialCapacity, DEFAULT_LOAD_FACTOR);

}

/**

* 采用默认容量16与默认加载系数0.75构建HashMap

*/

public HashMap() {

this.loadFactor = DEFAULT_LOAD_FACTOR;

threshold = (int) (DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);

table = new Entry[DEFAULT_INITIAL_CAPACITY];

init();

}

/**

*

* 根据指定Map中的键值对,默认加载因子构建HashMap

*/

public HashMap(Map<? extends K, ? extends V> m) {

this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, //size要小于容量*0.75

DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);

putAllForCreate(m);

}

// internal utilities

/**

*

* 在new table之后,在添加元素之前被调用

*/

void init() {

}

/**

*

* hash算法,根据key的hashCode计算其hash值

* 此算法看的一知半解,大家有兴趣可以查看其它资料

* >>>无符号右移 ^按位异或

*/

static int hash(int h) {

// This function ensures that hashCodes that differ only by

// constant multiples at each bit position have a bounded

// number of collisions (approximately 8 at default load factor).

h ^= (h >>> 20) ^ (h >>> 12);

return h ^ (h >>> 7) ^ (h >>> 4);

}

/**

* 根据hash值与数组长度计算其数组索引。

* length为2的幂,使不同hash通过h&(length-1)产生的索引尽量不同,即减少碰撞。

* 如果产生的索引都不同,通过找到索引就可以直接找到value,而不需要遍历链表。

* 可以使产生的索引始终在table索引范围之内

* 此方法详细解析可见:http://www.iteye.com/topic/539465

*/

static int indexFor(int h, int length) {

return h & (length - 1);

}

/**

* 键值对数目

*/

public int size() {

return size;

}

/**

* 判断hashMap是否为空

*/

public boolean isEmpty() {

return size == 0;

}

/**

*

* 通过key值获得value,如果没有找到此key则返回null。

* 不过返回null也可能是其value为null

* 通过contain方法可判断Map中是否含有此键

*

*/

public V get(Object key) {

if (key == null)
//空键另外处理

return getForNullKey();

int hash = hash(key.hashCode());

//定位到index,并查看e的下一个节点是否为null,否则继续遍历

for (Entry<K, V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {

Object k;

if (e.hash == hash && ((k = e.key) == key || key.equals(k)))

return e.value;

}

return null;

}

/**

*

* 空键的hash值为0,所以其数组中的索引为0.

* 独立把此方法分离出来是为了提高两个最常用的方法get和put的性能,

* 但在其它情况下此方法被合并了.

*/

private V getForNullKey() {

for (Entry<K, V> e = table[0]; e != null; e = e.next) {

if (e.key == null)

return e.value;

}

return null;

}

/**

* 如果Map中含有此key返回true.

* 具体见getEntry.

*/

public boolean containsKey(Object key) {

return getEntry(key) != null;

}

/**

*

* 通过返回Entry而不是value可确保Map中是否含有此key

*/

final Entry<K, V> getEntry(Object key) {

int hash = (key == null) ? 0 : hash(key.hashCode());

for (Entry<K, V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {

Object k;

if (e.hash == hash

&& ((k = e.key) == key || (key != null && key.equals(k))))

return e;

}

return null;

}

/**

*

* replaced.

* 通过指定的key值存储指定value,如果Map中含有此key则用指定value替换old value

*/

public V put(K key, V value) {

if (key == null)

return putForNullKey(value);

int hash = hash(key.hashCode());

int i = indexFor(hash, table.length);

for (Entry<K, V> e = table[i]; e != null; e = e.next) {

Object k;

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

V oldValue = e.value;

e.value = value;

e.recordAccess(this);
//当你调用put并在替换老值时会调用此方法,假如你在这个时候想做一些额外操作可继承Entry重写此方法

return oldValue;

}

}

modCount++;

addEntry(hash, key, value, i);

return null;

}

private V putForNullKey(V value) {

for (Entry<K, V> e = table[0]; e != null; e = e.next) {

if (e.key == null) {
//如果含有此null key替换老值

V oldValue = e.value;

e.value = value;

e.recordAccess(this);

return oldValue;

}

}

modCount++;

addEntry(0, null, value, 0);
//否则添加此Entry到数组

return null;

}

/**

*

* 此方法用来替代put方法,不会调整table大小。

* 此方法在确认map键值对个数始终小于table.length * load_factor,

* 添加元素时调用。主要是为了提高性能

*/

private void putForCreate(K key, V value) {

int hash = (key == null) ? 0 : hash(key.hashCode());

int i = indexFor(hash, table.length);

/**

*

* 查看是否存在同样的key值,如果有就替换其value

*/

for (Entry<K, V> e = table[i]; e != null; e = e.next) {

Object k;

if (e.hash == hash

&& ((k = e.key) == key || (key != null && key.equals(k)))) {

e.value = value;

return;

}

}

//否则添加一个Entry对象

createEntry(hash, key, value, i);

}

/**

* 依次遍历添加

* */

private void putAllForCreate(Map<? extends K, ? extends V> m) {

for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m

.entrySet().iterator(); i.hasNext();) {

Map.Entry<? extends K, ? extends V> e = i.next();

putForCreate(e.getKey(), e.getValue());

}

}

/**

*

* 当HashMap中元素越来越多时,发生碰撞的几率增大,为提高效率,当元素超过

* threshold时就要对数组进行扩充,扩充后,原数组中所有数据都要重新计算

* 其在新数组中的位置,所以每扩充一次对性能影响是非常大的。

*/

void resize(int newCapacity) {

Entry[] oldTable = table;

int oldCapacity = oldTable.length;

if (oldCapacity == MAXIMUM_CAPACITY) {
//如果数组容量已经最大,不再扩充。

threshold = Integer.MAX_VALUE;
//使threshold = Integer.MAX_VALUE,使resize方法不再被调用

return;

}

Entry[] newTable = new Entry[newCapacity];

transfer(newTable);

table = newTable;

threshold = (int) (newCapacity * loadFactor);

}

/**

*

* 把table中所有的Entry对象转移到newTabel

*/

void transfer(Entry[] newTable) {

Entry[] src = table;

int newCapacity = newTable.length;

for (int j = 0; j < src.length; j++) {

Entry<K, V> e = src[j];

if (e != null) {

src[j] = null;
//只置空第一个节点即可,因为此节点存在数组中

do {

Entry<K, V> next = e.next;

int i = indexFor(e.hash, newCapacity); //根据新容量重新计算index

e.next = newTable[i];
//最后添加的节点放最前面

newTable[i] = e;

e = next;

} while (e != null);

}

}

}

/**

*

* 把所有元素从知道map中复制到本map

*/

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

int numKeysToBeAdded = m.size();

if (numKeysToBeAdded == 0)

return;

/*

*

* 如果numKeysToBeAdded大于或等于threshold就扩展map

* 这是一个保守的方法。本来的条件应该是(m.size() + size) >= threshold,

* 但是如果所有被添加的元素的key值在本map中都存在,map扩充的容量将是

* 最佳容量的两倍。这极大的浪费了空间,所以采用此保守的方法计算newCapacity。

* 否则不再此处扩充就在put方法中进行扩充

*/

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);

}

//依次遍历添加

for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m

.entrySet().iterator(); i.hasNext();) {

Map.Entry<? extends K, ? extends V> e = i.next();

put(e.getKey(), e.getValue());

}

}

/**

* 根据知道key移除键值对,返回移除的元素

*/

public V remove(Object key) {

Entry<K, V> e = removeEntryForKey(key);

return (e == null ? null : e.value);

}

/**

* 根据key移除Entry对象

*/

final Entry<K, V> removeEntryForKey(Object key) {

int hash = (key == null) ? 0 : hash(key.hashCode());

int i = indexFor(hash, table.length);

Entry<K, V> prev = table[i];

Entry<K, V> e = prev;

while (e != null) {

Entry<K, V> next = e.next;

Object k;

if (e.hash == hash

&& ((k = e.key) == key || (key != null && key.equals(k)))) {

modCount++;

size--;

if (prev == e)
//表明链表只有一个Entry对象

table[i] = next;

else

prev.next = next;
//修改指针

e.recordRemoval(this);
//在移除元素时调用

return e;

}

prev = e;

e = next;

}

return e;

}

/**

* 同remove方法基本相似

*/

final Entry<K, V> removeMapping(Object o) {

if (!(o instanceof Map.Entry))

return null;

Map.Entry<K, V> entry = (Map.Entry<K, V>) o;

Object key = entry.getKey();

int hash = (key == null) ? 0 : hash(key.hashCode());

int i = indexFor(hash, table.length);

Entry<K, V> prev = table[i];

Entry<K, V> e = prev;

while (e != null) {

Entry<K, V> next = e.next;

if (e.hash == hash && e.equals(entry)) {

modCount++;

size--;

if (prev == e)

table[i] = next;

else

prev.next = next;

e.recordRemoval(this);

return e;

}

prev = e;

e = next;

}

return e;

}

/**

* 移除所有元素

*/

public void clear() {

modCount++;

Entry[] tab = table;

for (int i = 0; i < tab.length; i++)

tab[i] = null;
//只要把数组置空即可

size = 0;

}

/**

* 是否包含次value

*/

public boolean containsValue(Object value) {

if (value == null)

return containsNullValue();

Entry[] tab = table;

for (int i = 0; i < tab.length; i++)

for (Entry e = tab[i]; e != null; e = e.next)

if (value.equals(e.value))

return true;

return false;

}

/**

* 是否包含空值

*/

private boolean containsNullValue() {

Entry[] tab = table;

for (int i = 0; i < tab.length; i++)

for (Entry e = tab[i]; e != null; e = e.next)

if (e.value == null)

return true;

return false;

}

/**

* 返回HashMap的浅拷贝实例

*/

public Object clone() {

HashMap<K, V> result = null;

try {

result = (HashMap<K, V>) super.clone();

} catch (CloneNotSupportedException e) {

// assert false;

}

result.table = new Entry[table.length];

result.entrySet = null;

result.modCount = 0;

result.size = 0;

result.init();

result.putAllForCreate(this);
//依次添加本map所有元素到浅拷贝的map实例中

return result;

}

static class Entry<K, V> implements Map.Entry<K, V> {

final K key;

V value;

Entry<K, V> next;

final int hash;

/**

* Creates new entry.

*/

Entry(int h, K k, V v, Entry<K, V> n) {

value = v;

next = n;

key = k;

hash = h;

}

public final K getKey() {

return key;

}

public final V getValue() {

return value;

}

public final V setValue(V newValue) {

V oldValue = value;

value = newValue;

return oldValue;

}

//Entry的equals方法,键值相等即Entry对象相等

public final boolean equals(Object o) {

if (!(o instanceof Map.Entry))

return false;

Map.Entry e = (Map.Entry) o;

Object k1 = getKey();

Object k2 = e.getKey();

if (k1 == k2 || (k1 != null && k1.equals(k2))) {

Object v1 = getValue();

Object v2 = e.getValue();

if (v1 == v2 || (v1 != null && v1.equals(v2)))

return true;

}

return false;

}

/**

* 重写hashCode方法,异或key与value的hashCode值

*/

public final int hashCode() {

return (key == null ? 0 : key.hashCode())

^ (value == null ? 0 : value.hashCode());

}

public final String toString() {

return getKey() + "=" + getValue();

}

/**

*

* 当添加一键值对,发现键已存在时调用此方法

* 可以继承Entry对象重写此方法

*/

void recordAccess(HashMap<K, V> m) {

}

/**

* 当有Entry对象被移除时,此方法被调用。

* 可以继承Entry对象重写此方法

*/

void recordRemoval(HashMap<K, V> m) {

}

}

/**

*

* 如果适当此方法会resize table

*/

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

Entry<K, V> e = table[bucketIndex];

table[bucketIndex] = new Entry<K, V>(hash, key, value, e);

if (size++ >= threshold)
//如果size超过threshold就调整数组容量大小为原来的两倍

resize(2 * table.length);

}

/**

*

* 与addEntry方法类似。但是方法不需要担心容量的扩充

*/

void createEntry(int hash, K key, V value, int bucketIndex) {

Entry<K, V> e = table[bucketIndex];
//如果此节点已经有一个Entry对象,返回e,否则返回null

table[bucketIndex] = new Entry<K, V>(hash, key, value, e);
//以新加入的节点作为第一个节点

size++;

}

/**

* 抽象类,next方法由其子类实现,

* 不同的next方法返回不同的迭代器

* 包括key,value,keySet迭代器

* */

private abstract class HashIterator<E> implements Iterator<E> {

Entry<K, V> next; // next entry to return

int expectedModCount; // For fast-fail

int index; // current slot

Entry<K, V> current; // current entry

HashIterator() {

expectedModCount = modCount;

if (size > 0) { // advance to first entry

Entry[] t = table;

//遍历直到获取第一个Entry对象,因为有的索引可能为空

while (index < t.length && (next = t[index++]) == null)

;

}

}

public final boolean hasNext() {

return next != null;

}

/**

* 返回下一个Entry对象

* */

final Entry<K, V> nextEntry() {

if (modCount != expectedModCount)

throw new ConcurrentModificationException();

Entry<K, V> e = next;

if (e == null)

throw new NoSuchElementException();

if ((next = e.next) == null) {

Entry[] t = table;

//继续找不为空的索引中的Entry对象

while (index < t.length && (next = t[index++]) == null)

;

}

current = e;

return e;

}

/**

* 移除当前Entry对象,即调用nextEntry返回的Entry对象

*/

public void remove() {

if (current == null)

throw new IllegalStateException();

if (modCount != expectedModCount)

throw new ConcurrentModificationException();

Object k = current.key;

current = null;

HashMap.this.removeEntryForKey(k);
//此方法会改变modCount

expectedModCount = modCount;
//所以可以用此语句检测是否产生了并发操作

}

}

//依次重写next方法,返回不同的迭代器。

private final class ValueIterator extends HashIterator<V> {

public V next() {

return nextEntry().value;

}

}

private final class KeyIterator extends HashIterator<K> {

public K next() {

return nextEntry().getKey();

}

}

private final class EntryIterator extends HashIterator<Map.Entry<K, V>> {

public Map.Entry<K, V> next() {

return nextEntry();

}

}

// Subclass overrides these to alter behavior of views' iterator() method

Iterator<K> newKeyIterator() {

return new KeyIterator();

}

Iterator<V> newValueIterator() {

return new ValueIterator();

}

Iterator<Map.Entry<K, V>> newEntryIterator() {

return new EntryIterator();

}

// Views

private transient Set<Map.Entry<K, V>> entrySet = null;

/**

* 返回一个key集。

* 此Set集合只在第一次调用keySet()时被创建,此后返回的都是同一个Set。

* 此方法不是线程安全的,大量线程多次调用此方法返回的可能不是同一个Set(可能是重新new的)

*

* 对map的修改会反应到Set当中,相反,对Set中key进行移除操作,比如

* Iterator.remove,Set.remove ,removeAll,retainAll,clear等操作时被移除的键

* 和它相关联的值也将从map中被移除,但是此Set不支持任何添加操作

*/

public Set<K> keySet() {

Set<K> ks = keySet;

return (ks != null ? ks : (keySet = new KeySet()));

}

private final class KeySet extends AbstractSet<K> {

public Iterator<K> iterator() {

return newKeyIterator();

}

public int size() {

return size;

}

public boolean contains(Object o) {

return containsKey(o);

}

/**

* 重写了Set的remove方法,

* 父类remove都是调用迭代器的remove方法

* */

public boolean remove(Object o) {

return HashMap.this.removeEntryForKey(o) != null;

}

public void clear() {

HashMap.this.clear();

}

}

/**

* 同上

*/

public Collection<V> values() {

Collection<V> vs = values;

return (vs != null ? vs : (values = new Values()));

}

private final class Values extends AbstractCollection<V> {

public Iterator<V> iterator() {

return newValueIterator();

}

public int size() {

return size;

}

public boolean contains(Object o) {

return containsValue(o);

}

public void clear() {

HashMap.this.clear();

}

}

/**

* 同上

*/

public Set<Map.Entry<K, V>> entrySet() {

return entrySet0();

}

private Set<Map.Entry<K, V>> entrySet0() {

Set<Map.Entry<K, V>> es = entrySet;

return es != null ? es : (entrySet = new EntrySet());

}

private final class EntrySet extends AbstractSet<Map.Entry<K, V>> {

public Iterator<Map.Entry<K, V>> iterator() {

return newEntryIterator();

}

public boolean contains(Object o) {

if (!(o instanceof Map.Entry))

return false;

Map.Entry<K, V> e = (Map.Entry<K, V>) o;

Entry<K, V> candidate = getEntry(e.getKey());

return candidate != null && candidate.equals(e);

}

public boolean remove(Object o) {

return removeMapping(o) != null;

}

public int size() {

return size;

}

public void clear() {

HashMap.this.clear();

}

}

/**

* 序列化hashMap对象

*/

private void writeObject(java.io.ObjectOutputStream s) throws IOException {

Iterator<Map.Entry<K, V>> i = (size > 0) ? entrySet0().iterator()

: null;

// 写入默认信息

s.defaultWriteObject();

// 写入可以存储的容量

s.writeInt(table.length);

// 写入实际长度

s.writeInt(size);

// Write out keys and values (alternating)

if (i != null) {

while (i.hasNext()) {
//依次写入键值对

Map.Entry<K, V> e = i.next();

s.writeObject(e.getKey());

s.writeObject(e.getValue());

}

}

}

private static final long serialVersionUID = 362498820763181265L;

/**

* 读出HashMap对象

*/

private void readObject(java.io.ObjectInputStream s) throws IOException,

ClassNotFoundException {

//读出默认信息

s.defaultReadObject();

// 读容量

int numBuckets = s.readInt();

table = new Entry[numBuckets];

init(); // Give subclass a chance to do its thing.

// 读长度

int size = s.readInt();

//读键值对,并还原HashMap元素

for (int i = 0; i < size; i++) {

K key = (K) s.readObject();

V value = (V) s.readObject();

putForCreate(key, value);

}

}

// These methods are used when serializing HashSets

int capacity() {

return table.length;

}

float loadFactor() {

return loadFactor;

}

}

/**

* 作用:用于实现快速查找

* HashMap实现的数据结构:动态数组和链表的结合体

* */

public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>,

Cloneable, Serializable {

/**

* 默认初始数组容量,必须为2的幂

*/

static final int DEFAULT_INITIAL_CAPACITY = 16;

/**

*

* 最大容量为1 * 2^30 即2的30次方

*/

static final int MAXIMUM_CAPACITY = 1 << 30;

/**

*

* hashMap的加载系数,当数组中的元素增多时,通过hash函数算出的数组下标

* 相同几率增加。为保证查找的效率,当数组中的元素超过

* load_factor * table.length 时就要扩充容量

* 默认加载系数为0.75

*/

static final float DEFAULT_LOAD_FACTOR = 0.75f;

/**

*

* 数组存放Entry对象,单向链表的第一个元素,

* 通过它可以遍历整个链表。

* table长度会在需要时进行扩充,table长度始终为2的幂

*/

transient Entry[] table;

/**

* key-value键值对个数

*/

transient int size;

/**

* HashMap size >= threshlod时就扩充数组容量

*/

int threshold;

/**

* hash表加载因子

*/

final float loadFactor;

/**

*

* hash表发生结构性改变的次数,这些方法包括,put,remove等对size进行改变的操作

* 用iterator遍历时可以用来检测是否对HashMap进行了并发操作

*/

transient volatile int modCount;

/**

* 根据指定的初始容量和加载系数构建hashMap

* 初始容量如果不是2的幂,会被构造成2的幂

*/

public HashMap(int initialCapacity, float loadFactor) {

if (initialCapacity < 0)

throw new IllegalArgumentException("Illegal initial capacity: "

+ initialCapacity);

if (initialCapacity > MAXIMUM_CAPACITY)

initialCapacity = MAXIMUM_CAPACITY;

if (loadFactor <= 0 || Float.isNaN(loadFactor))

throw new IllegalArgumentException("Illegal load factor: "

+ loadFactor);

//找到一个2的幂的数,使其大于等于初始容量

int capacity = 1;

while (capacity < initialCapacity)

capacity <<= 1;
// capacity = capacity << 1,左移一位

this.loadFactor = loadFactor;

threshold = (int) (capacity * loadFactor);

table = new Entry[capacity];

init();
//所有构造方法都含有此空方法,做一些其他初始化操作。根据业务要求,可由其子类实现

}

/**

* 根据指定容量与默认加载系数构建HashMap

*/

public HashMap(int initialCapacity) {

this(initialCapacity, DEFAULT_LOAD_FACTOR);

}

/**

* 采用默认容量16与默认加载系数0.75构建HashMap

*/

public HashMap() {

this.loadFactor = DEFAULT_LOAD_FACTOR;

threshold = (int) (DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);

table = new Entry[DEFAULT_INITIAL_CAPACITY];

init();

}

/**

*

* 根据指定Map中的键值对,默认加载因子构建HashMap

*/

public HashMap(Map<? extends K, ? extends V> m) {

this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, //size要小于容量*0.75

DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);

putAllForCreate(m);

}

// internal utilities

/**

*

* 在new table之后,在添加元素之前被调用

*/

void init() {

}

/**

*

* hash算法,根据key的hashCode计算其hash值

* 此算法看的一知半解,大家有兴趣可以查看其它资料

* >>>无符号右移 ^按位异或

*/

static int hash(int h) {

// This function ensures that hashCodes that differ only by

// constant multiples at each bit position have a bounded

// number of collisions (approximately 8 at default load factor).

h ^= (h >>> 20) ^ (h >>> 12);

return h ^ (h >>> 7) ^ (h >>> 4);

}

/**

* 根据hash值与数组长度计算其数组索引。

* length为2的幂,使不同hash通过h&(length-1)产生的索引尽量不同,即减少碰撞。

* 如果产生的索引都不同,通过找到索引就可以直接找到value,而不需要遍历链表。

* 可以使产生的索引始终在table索引范围之内

* 此方法详细解析可见:http://www.iteye.com/topic/539465

*/

static int indexFor(int h, int length) {

return h & (length - 1);

}

/**

* 键值对数目

*/

public int size() {

return size;

}

/**

* 判断hashMap是否为空

*/

public boolean isEmpty() {

return size == 0;

}

/**

*

* 通过key值获得value,如果没有找到此key则返回null。

* 不过返回null也可能是其value为null

* 通过contain方法可判断Map中是否含有此键

*

*/

public V get(Object key) {

if (key == null)
//空键另外处理

return getForNullKey();

int hash = hash(key.hashCode());

//定位到index,并查看e的下一个节点是否为null,否则继续遍历

for (Entry<K, V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {

Object k;

if (e.hash == hash && ((k = e.key) == key || key.equals(k)))

return e.value;

}

return null;

}

/**

*

* 空键的hash值为0,所以其数组中的索引为0.

* 独立把此方法分离出来是为了提高两个最常用的方法get和put的性能,

* 但在其它情况下此方法被合并了.

*/

private V getForNullKey() {

for (Entry<K, V> e = table[0]; e != null; e = e.next) {

if (e.key == null)

return e.value;

}

return null;

}

/**

* 如果Map中含有此key返回true.

* 具体见getEntry.

*/

public boolean containsKey(Object key) {

return getEntry(key) != null;

}

/**

*

* 通过返回Entry而不是value可确保Map中是否含有此key

*/

final Entry<K, V> getEntry(Object key) {

int hash = (key == null) ? 0 : hash(key.hashCode());

for (Entry<K, V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {

Object k;

if (e.hash == hash

&& ((k = e.key) == key || (key != null && key.equals(k))))

return e;

}

return null;

}

/**

*

* replaced.

* 通过指定的key值存储指定value,如果Map中含有此key则用指定value替换old value

*/

public V put(K key, V value) {

if (key == null)

return putForNullKey(value);

int hash = hash(key.hashCode());

int i = indexFor(hash, table.length);

for (Entry<K, V> e = table[i]; e != null; e = e.next) {

Object k;

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

V oldValue = e.value;

e.value = value;

e.recordAccess(this);
//当你调用put并在替换老值时会调用此方法,假如你在这个时候想做一些额外操作可继承Entry重写此方法

return oldValue;

}

}

modCount++;

addEntry(hash, key, value, i);

return null;

}

private V putForNullKey(V value) {

for (Entry<K, V> e = table[0]; e != null; e = e.next) {

if (e.key == null) {
//如果含有此null key替换老值

V oldValue = e.value;

e.value = value;

e.recordAccess(this);

return oldValue;

}

}

modCount++;

addEntry(0, null, value, 0);
//否则添加此Entry到数组

return null;

}

/**

*

* 此方法用来替代put方法,不会调整table大小。

* 此方法在确认map键值对个数始终小于table.length * load_factor,

* 添加元素时调用。主要是为了提高性能

*/

private void putForCreate(K key, V value) {

int hash = (key == null) ? 0 : hash(key.hashCode());

int i = indexFor(hash, table.length);

/**

*

* 查看是否存在同样的key值,如果有就替换其value

*/

for (Entry<K, V> e = table[i]; e != null; e = e.next) {

Object k;

if (e.hash == hash

&& ((k = e.key) == key || (key != null && key.equals(k)))) {

e.value = value;

return;

}

}

//否则添加一个Entry对象

createEntry(hash, key, value, i);

}

/**

* 依次遍历添加

* */

private void putAllForCreate(Map<? extends K, ? extends V> m) {

for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m

.entrySet().iterator(); i.hasNext();) {

Map.Entry<? extends K, ? extends V> e = i.next();

putForCreate(e.getKey(), e.getValue());

}

}

/**

*

* 当HashMap中元素越来越多时,发生碰撞的几率增大,为提高效率,当元素超过

* threshold时就要对数组进行扩充,扩充后,原数组中所有数据都要重新计算

* 其在新数组中的位置,所以每扩充一次对性能影响是非常大的。

*/

void resize(int newCapacity) {

Entry[] oldTable = table;

int oldCapacity = oldTable.length;

if (oldCapacity == MAXIMUM_CAPACITY) {
//如果数组容量已经最大,不再扩充。

threshold = Integer.MAX_VALUE;
//使threshold = Integer.MAX_VALUE,使resize方法不再被调用

return;

}

Entry[] newTable = new Entry[newCapacity];

transfer(newTable);

table = newTable;

threshold = (int) (newCapacity * loadFactor);

}

/**

*

* 把table中所有的Entry对象转移到newTabel

*/

void transfer(Entry[] newTable) {

Entry[] src = table;

int newCapacity = newTable.length;

for (int j = 0; j < src.length; j++) {

Entry<K, V> e = src[j];

if (e != null) {

src[j] = null;
//只置空第一个节点即可,因为此节点存在数组中

do {

Entry<K, V> next = e.next;

int i = indexFor(e.hash, newCapacity); //根据新容量重新计算index

e.next = newTable[i];
//最后添加的节点放最前面

newTable[i] = e;

e = next;

} while (e != null);

}

}

}

/**

*

* 把所有元素从知道map中复制到本map

*/

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

int numKeysToBeAdded = m.size();

if (numKeysToBeAdded == 0)

return;

/*

*

* 如果numKeysToBeAdded大于或等于threshold就扩展map

* 这是一个保守的方法。本来的条件应该是(m.size() + size) >= threshold,

* 但是如果所有被添加的元素的key值在本map中都存在,map扩充的容量将是

* 最佳容量的两倍。这极大的浪费了空间,所以采用此保守的方法计算newCapacity。

* 否则不再此处扩充就在put方法中进行扩充

*/

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);

}

//依次遍历添加

for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m

.entrySet().iterator(); i.hasNext();) {

Map.Entry<? extends K, ? extends V> e = i.next();

put(e.getKey(), e.getValue());

}

}

/**

* 根据知道key移除键值对,返回移除的元素

*/

public V remove(Object key) {

Entry<K, V> e = removeEntryForKey(key);

return (e == null ? null : e.value);

}

/**

* 根据key移除Entry对象

*/

final Entry<K, V> removeEntryForKey(Object key) {

int hash = (key == null) ? 0 : hash(key.hashCode());

int i = indexFor(hash, table.length);

Entry<K, V> prev = table[i];

Entry<K, V> e = prev;

while (e != null) {

Entry<K, V> next = e.next;

Object k;

if (e.hash == hash

&& ((k = e.key) == key || (key != null && key.equals(k)))) {

modCount++;

size--;

if (prev == e)
//表明链表只有一个Entry对象

table[i] = next;

else

prev.next = next;
//修改指针

e.recordRemoval(this);
//在移除元素时调用

return e;

}

prev = e;

e = next;

}

return e;

}

/**

* 同remove方法基本相似

*/

final Entry<K, V> removeMapping(Object o) {

if (!(o instanceof Map.Entry))

return null;

Map.Entry<K, V> entry = (Map.Entry<K, V>) o;

Object key = entry.getKey();

int hash = (key == null) ? 0 : hash(key.hashCode());

int i = indexFor(hash, table.length);

Entry<K, V> prev = table[i];

Entry<K, V> e = prev;

while (e != null) {

Entry<K, V> next = e.next;

if (e.hash == hash && e.equals(entry)) {

modCount++;

size--;

if (prev == e)

table[i] = next;

else

prev.next = next;

e.recordRemoval(this);

return e;

}

prev = e;

e = next;

}

return e;

}

/**

* 移除所有元素

*/

public void clear() {

modCount++;

Entry[] tab = table;

for (int i = 0; i < tab.length; i++)

tab[i] = null;
//只要把数组置空即可

size = 0;

}

/**

* 是否包含次value

*/

public boolean containsValue(Object value) {

if (value == null)

return containsNullValue();

Entry[] tab = table;

for (int i = 0; i < tab.length; i++)

for (Entry e = tab[i]; e != null; e = e.next)

if (value.equals(e.value))

return true;

return false;

}

/**

* 是否包含空值

*/

private boolean containsNullValue() {

Entry[] tab = table;

for (int i = 0; i < tab.length; i++)

for (Entry e = tab[i]; e != null; e = e.next)

if (e.value == null)

return true;

return false;

}

/**

* 返回HashMap的浅拷贝实例

*/

public Object clone() {

HashMap<K, V> result = null;

try {

result = (HashMap<K, V>) super.clone();

} catch (CloneNotSupportedException e) {

// assert false;

}

result.table = new Entry[table.length];

result.entrySet = null;

result.modCount = 0;

result.size = 0;

result.init();

result.putAllForCreate(this);
//依次添加本map所有元素到浅拷贝的map实例中

return result;

}

static class Entry<K, V> implements Map.Entry<K, V> {

final K key;

V value;

Entry<K, V> next;

final int hash;

/**

* Creates new entry.

*/

Entry(int h, K k, V v, Entry<K, V> n) {

value = v;

next = n;

key = k;

hash = h;

}

public final K getKey() {

return key;

}

public final V getValue() {

return value;

}

public final V setValue(V newValue) {

V oldValue = value;

value = newValue;

return oldValue;

}

//Entry的equals方法,键值相等即Entry对象相等

public final boolean equals(Object o) {

if (!(o instanceof Map.Entry))

return false;

Map.Entry e = (Map.Entry) o;

Object k1 = getKey();

Object k2 = e.getKey();

if (k1 == k2 || (k1 != null && k1.equals(k2))) {

Object v1 = getValue();

Object v2 = e.getValue();

if (v1 == v2 || (v1 != null && v1.equals(v2)))

return true;

}

return false;

}

/**

* 重写hashCode方法,异或key与value的hashCode值

*/

public final int hashCode() {

return (key == null ? 0 : key.hashCode())

^ (value == null ? 0 : value.hashCode());

}

public final String toString() {

return getKey() + "=" + getValue();

}

/**

*

* 当添加一键值对,发现键已存在时调用此方法

* 可以继承Entry对象重写此方法

*/

void recordAccess(HashMap<K, V> m) {

}

/**

* 当有Entry对象被移除时,此方法被调用。

* 可以继承Entry对象重写此方法

*/

void recordRemoval(HashMap<K, V> m) {

}

}

/**

*

* 如果适当此方法会resize table

*/

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

Entry<K, V> e = table[bucketIndex];

table[bucketIndex] = new Entry<K, V>(hash, key, value, e);

if (size++ >= threshold)
//如果size超过threshold就调整数组容量大小为原来的两倍

resize(2 * table.length);

}

/**

*

* 与addEntry方法类似。但是方法不需要担心容量的扩充

*/

void createEntry(int hash, K key, V value, int bucketIndex) {

Entry<K, V> e = table[bucketIndex];
//如果此节点已经有一个Entry对象,返回e,否则返回null

table[bucketIndex] = new Entry<K, V>(hash, key, value, e);
//以新加入的节点作为第一个节点

size++;

}

/**

* 抽象类,next方法由其子类实现,

* 不同的next方法返回不同的迭代器

* 包括key,value,keySet迭代器

* */

private abstract class HashIterator<E> implements Iterator<E> {

Entry<K, V> next; // next entry to return

int expectedModCount; // For fast-fail

int index; // current slot

Entry<K, V> current; // current entry

HashIterator() {

expectedModCount = modCount;

if (size > 0) { // advance to first entry

Entry[] t = table;

//遍历直到获取第一个Entry对象,因为有的索引可能为空

while (index < t.length && (next = t[index++]) == null)

;

}

}

public final boolean hasNext() {

return next != null;

}

/**

* 返回下一个Entry对象

* */

final Entry<K, V> nextEntry() {

if (modCount != expectedModCount)

throw new ConcurrentModificationException();

Entry<K, V> e = next;

if (e == null)

throw new NoSuchElementException();

if ((next = e.next) == null) {

Entry[] t = table;

//继续找不为空的索引中的Entry对象

while (index < t.length && (next = t[index++]) == null)

;

}

current = e;

return e;

}

/**

* 移除当前Entry对象,即调用nextEntry返回的Entry对象

*/

public void remove() {

if (current == null)

throw new IllegalStateException();

if (modCount != expectedModCount)

throw new ConcurrentModificationException();

Object k = current.key;

current = null;

HashMap.this.removeEntryForKey(k);
//此方法会改变modCount

expectedModCount = modCount;
//所以可以用此语句检测是否产生了并发操作

}

}

//依次重写next方法,返回不同的迭代器。

private final class ValueIterator extends HashIterator<V> {

public V next() {

return nextEntry().value;

}

}

private final class KeyIterator extends HashIterator<K> {

public K next() {

return nextEntry().getKey();

}

}

private final class EntryIterator extends HashIterator<Map.Entry<K, V>> {

public Map.Entry<K, V> next() {

return nextEntry();

}

}

// Subclass overrides these to alter behavior of views' iterator() method

Iterator<K> newKeyIterator() {

return new KeyIterator();

}

Iterator<V> newValueIterator() {

return new ValueIterator();

}

Iterator<Map.Entry<K, V>> newEntryIterator() {

return new EntryIterator();

}

// Views

private transient Set<Map.Entry<K, V>> entrySet = null;

/**

* 返回一个key集。

* 此Set集合只在第一次调用keySet()时被创建,此后返回的都是同一个Set。

* 此方法不是线程安全的,大量线程多次调用此方法返回的可能不是同一个Set(可能是重新new的)

*

* 对map的修改会反应到Set当中,相反,对Set中key进行移除操作,比如

* Iterator.remove,Set.remove ,removeAll,retainAll,clear等操作时被移除的键

* 和它相关联的值也将从map中被移除,但是此Set不支持任何添加操作

*/

public Set<K> keySet() {

Set<K> ks = keySet;

return (ks != null ? ks : (keySet = new KeySet()));

}

private final class KeySet extends AbstractSet<K> {

public Iterator<K> iterator() {

return newKeyIterator();

}

public int size() {

return size;

}

public boolean contains(Object o) {

return containsKey(o);

}

/**

* 重写了Set的remove方法,

* 父类remove都是调用迭代器的remove方法

* */

public boolean remove(Object o) {

return HashMap.this.removeEntryForKey(o) != null;

}

public void clear() {

HashMap.this.clear();

}

}

/**

* 同上

*/

public Collection<V> values() {

Collection<V> vs = values;

return (vs != null ? vs : (values = new Values()));

}

private final class Values extends AbstractCollection<V> {

public Iterator<V> iterator() {

return newValueIterator();

}

public int size() {

return size;

}

public boolean contains(Object o) {

return containsValue(o);

}

public void clear() {

HashMap.this.clear();

}

}

/**

* 同上

*/

public Set<Map.Entry<K, V>> entrySet() {

return entrySet0();

}

private Set<Map.Entry<K, V>> entrySet0() {

Set<Map.Entry<K, V>> es = entrySet;

return es != null ? es : (entrySet = new EntrySet());

}

private final class EntrySet extends AbstractSet<Map.Entry<K, V>> {

public Iterator<Map.Entry<K, V>> iterator() {

return newEntryIterator();

}

public boolean contains(Object o) {

if (!(o instanceof Map.Entry))

return false;

Map.Entry<K, V> e = (Map.Entry<K, V>) o;

Entry<K, V> candidate = getEntry(e.getKey());

return candidate != null && candidate.equals(e);

}

public boolean remove(Object o) {

return removeMapping(o) != null;

}

public int size() {

return size;

}

public void clear() {

HashMap.this.clear();

}

}

/**

* 序列化hashMap对象

*/

private void writeObject(java.io.ObjectOutputStream s) throws IOException {

Iterator<Map.Entry<K, V>> i = (size > 0) ? entrySet0().iterator()

: null;

// 写入默认信息

s.defaultWriteObject();

// 写入可以存储的容量

s.writeInt(table.length);

// 写入实际长度

s.writeInt(size);

// Write out keys and values (alternating)

if (i != null) {

while (i.hasNext()) {
//依次写入键值对

Map.Entry<K, V> e = i.next();

s.writeObject(e.getKey());

s.writeObject(e.getValue());

}

}

}

private static final long serialVersionUID = 362498820763181265L;

/**

* 读出HashMap对象

*/

private void readObject(java.io.ObjectInputStream s) throws IOException,

ClassNotFoundException {

//读出默认信息

s.defaultReadObject();

// 读容量

int numBuckets = s.readInt();

table = new Entry[numBuckets];

init(); // Give subclass a chance to do its thing.

// 读长度

int size = s.readInt();

//读键值对,并还原HashMap元素

for (int i = 0; i < size; i++) {

K key = (K) s.readObject();

V value = (V) s.readObject();

putForCreate(key, value);

}

}

// These methods are used when serializing HashSets

int capacity() {

return table.length;

}

float loadFactor() {

return loadFactor;

}

}

四。HashSet

/**

* 散列集(hashSet),就是不存在重复元素的集合。

* HashSet是在HashMap的基础上实现的,

* 以HashSet的元素做Key值使其值不会重复

* */

public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable,

java.io.Serializable {

static final long serialVersionUID = -5024744406713321676L;

private transient HashMap<E, Object> map;

//以Object作为虚假的Value值

private static final Object PRESENT = new Object();

/**

*

* 构造一个新的,空Set集;

* 实际是构造一个默认初始容量为16,加载因子为0.75的空HashMap

*/

public HashSet() {

map = new HashMap<E, Object>();

}

/**

*

* 构造一个包含指定集合c中所有元素的新的Set集。

* 实际是构造包含集合c中所有元素的HashMap.

* 初始大小必须大于容量*0.75

*

*/

public HashSet(Collection<? extends E> c) {

map = new HashMap<E, Object>(Math.max((int) (c.size() / .75f) + 1, 16));

addAll(c);

}

/**

* 以指定初始容量和加载因子构造HashMap

*/

public HashSet(int initialCapacity, float loadFactor) {

map = new HashMap<E, Object>(initialCapacity, loadFactor);

}

/**

* 以初始容量构造HashMap

*/

public HashSet(int initialCapacity) {

map = new HashMap<E, Object>(initialCapacity);

}

/**

*

* 构造一个Linked hash set.

* 以指定初始容量,加载因子构造LinkedHashMap,dummy只是为了区别其他构造方法

*

*/

HashSet(int initialCapacity, float loadFactor, boolean dummy) {

map = new LinkedHashMap<E, Object>(initialCapacity, loadFactor);

}

/**

* 获得HashMap的键集迭代器

*/

public Iterator<E> iterator() {

return map.keySet().iterator();

}

/**

* 返回元素个数

*/

public int size() {

return map.size();

}

/**

* 判断Hash集是否为空

*/

public boolean isEmpty() {

return map.isEmpty();

}

/**

* 如果Map中含有此key则返回true

*/

public boolean contains(Object o) {

return map.containsKey(o);

}

/**

*

* 如果e不存在于Set中则添加e到集合,

* 如果Map中key集不存在e,则添加并返回null,否则替换原来的value,返回oldValue

*

*/

public boolean add(E e) {

return map.put(e, PRESENT) == null;

}

/**

* 移除指定元素

*/

public boolean remove(Object o) {

return map.remove(o) == PRESENT;

}

/**

* 清空map

*/

public void clear() {

map.clear();

}

/**

* 返回HashSet的浅拷贝对象

*/

public Object clone() {

try {

HashSet<E> newSet = (HashSet<E>) super.clone();

newSet.map = (HashMap<E, Object>) map.clone();

return newSet;

} catch (CloneNotSupportedException e) {

throw new InternalError();

}

}

private void writeObject(java.io.ObjectOutputStream s)

throws java.io.IOException {

// Write out any hidden serialization magic

s.defaultWriteObject();

//写入HashMap的容量和加载系数

s.writeInt(map.capacity());

s.writeFloat(map.loadFactor());

//写入size

s.writeInt(map.size());

//依次写入键值

for (Iterator i = map.keySet().iterator(); i.hasNext();)

s.writeObject(i.next());

}

private void readObject(java.io.ObjectInputStream s)

throws java.io.IOException, ClassNotFoundException {

// Read in any hidden serialization magic

s.defaultReadObject();

//读取容量和加载因子构造HashMap

int capacity = s.readInt();

float loadFactor = s.readFloat();

//判断是LinkedHashMap还是HashMap

map = (((HashSet) this) instanceof LinkedHashSet ? new LinkedHashMap<E, Object>(

capacity, loadFactor)

: new HashMap<E, Object>(capacity, loadFactor));

// 读size

int size = s.readInt();

//依次读出所有元素

for (int i = 0; i < size; i++) {

E e = (E) s.readObject();

map.put(e, PRESENT);

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐