一。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);
}
}
}

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

  1. 集合框架源码分析四(Collections类详细分析)

    我认为Collections类主要是完成了两个主要功能  1.提供了若干简单而又有用的算法,比如排序,二分查找,求最大最小值等等.  2.提供对集合进行包装的静态方法.比如把指定的集合包装成线程安全的 ...

  2. 【投屏】Scrcpy源码分析三(Client篇-投屏阶段)

    Scrcpy源码分析系列 [投屏]Scrcpy源码分析一(编译篇) [投屏]Scrcpy源码分析二(Client篇-连接阶段) [投屏]Scrcpy源码分析三(Client篇-投屏阶段) [投屏]Sc ...

  3. 集合框架源码分析一(接口篇)

    一.Iterable接口 public interface Iterable<T> { /**      * 实现此接口的所有集合都可以使用foreach循环      * 由于Colle ...

  4. 集合框架源码分析六之堆结构的实现(PriorityQueue)

    /** * * 优先队列是用了一种叫做堆的高效的数据结构, * 堆是用二叉树来描述的,对任意元素n,索引从0开始,如果有子节点的话,则左子树为 * 2*n+1,右子树为2*(n+1). * 以堆实现的 ...

  5. 集合框架源码分析五之LinkedHashMap,LinkedHashSet

    LinkedHashMap是为了解决遍历Hash表的无序问题,它内部维护了一个链表用于记录你插入元素(或你访问元素的顺序)的位置,遍历时直接遍历链表,元素的顺序即为你插入的顺序,但是Entry对象要多 ...

  6. 集合框架源码分析——抽象类

    public abstract class AbstractCollection<E> implements Collection<E> {     /**      * 唯一 ...

  7. 【投屏】Scrcpy源码分析二(Client篇-连接阶段)

    Scrcpy源码分析系列 [投屏]Scrcpy源码分析一(编译篇) [投屏]Scrcpy源码分析二(Client篇-连接阶段) [投屏]Scrcpy源码分析三(Client篇-投屏阶段) [投屏]Sc ...

  8. 【投屏】Scrcpy源码分析一(编译篇)

    Scrcpy源码分析系列 [投屏]Scrcpy源码分析一(编译篇) [投屏]Scrcpy源码分析二(Client篇-连接阶段) [投屏]Scrcpy源码分析三(Client篇-投屏阶段) [投屏]Sc ...

  9. 集合底层源码分析之HashMap《上》(三)

    集合底层源码分析之HashMap<上>(三) 前言 源码分析 HashMap主要属性及构造方法分析 tableSizeFor()方法源码分析 Node类源码分析 TreeNode类源码分析 ...

最新文章

  1. 微软云计算介绍与实践(实践之十七)
  2. 如何从文件的完整路径获取目录?
  3. Matlab中gradient函数的使用方法
  4. sql int 比较_高质量SQL的30条建议 建议你收藏
  5. 通俗易懂,快速幂基本思想
  6. java String部分源码解析
  7. MooTools教程(2):DOM选择器
  8. MTK 驱动开发(40 )---TP乱跳频原因
  9. 网络图的绘制方法详细讲解
  10. 海外版mate9刷机国行android 8.0系统
  11. Deepin20.4系统中wine优化设置
  12. bzoj3168 [Heoi2013]钙铁锌硒维生素(矩阵求逆+匈牙利)
  13. springboot+二手车交易系统 毕业设计-附源码131456
  14. 免安装版jdk的配置及使用(附绿色版jdk1.7及jdk1.8)
  15. 电脑如何同时安装JDK11和JDK1.8(适用于多个JDK)
  16. 历史库存sap_SAP 常用的库存表
  17. WebGIS学习路线
  18. 车载以太网解决方案 助力智能网联汽车开发
  19. Carmichael function[卡迈克尔函数相关性质]
  20. 【LeetCode Python实现】908. 最小差值 I(简单)

热门文章

  1. Android 亲测源码分享
  2. “tel.xls.exe病毒”解决方法
  3. C2146和C4430错误:循环引用错误
  4. Ants UVA - 1411(km板题竟然让我换了个板子)
  5. c++笔试题两道,求解当中一道
  6. 通过Iframe在A网站页面内嵌入空白页面的方式,跨域获取B网站的数据返回给A网站!...
  7. 驱动相关的内核函数分析
  8. z-index的最大值、最小值
  9. 【转】Photoshop网站设计:DesignStudio
  10. SyntaxHighlighter Evolved高亮插件的编程语言及语言别名对照表