`
zhouYunan2010
  • 浏览: 207658 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
社区版块
存档分类

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

 
阅读更多
一。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;
	}
}



四。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);
		}
	}
}
分享到:
评论
1 楼 minixalpha 2014-05-18  
我发现一个问题,ArrayList和LinkedList在writeObject函数中有一个不一样的地方,前者对modCount进行了检查,后者没有,有什么特别的考虑吗?

相关推荐

    集合框架源码分析

    常见的实现类有`ArrayList`、`LinkedList`、`HashSet`、`LinkedHashSet`、`HashMap`等。 2. **源码分析:ArrayList** `ArrayList`是基于动态数组实现的列表,其内部维护了一个Object类型的数组。当我们添加元素时...

    51. ArrayList LinkedList Set HashMap介绍.txt

    `ArrayList` 是 Java 中的一种动态数组实现方式,它允许在运行时调整其大小。`ArrayList` 实现了 `List` 接口,并且内部通过一个数组来存储数据。当添加元素导致数组空间不足时,`ArrayList` 会创建一个新的更大的...

    深入arraylist,linkedlist,hashmap,hashset源码(2012/3/18)

    在Java编程语言中,ArrayList、LinkedList、HashMap和HashSet是四个非常重要的集合类,它们分别代表了不同类型的数据结构。这篇文章将深入探讨这些类的源码,以帮助我们更好地理解和运用它们。 首先,ArrayList是一...

    ArrayList和Linkedlist1

    在IT领域,特别是Java编程中,ArrayList和LinkedList是两种非常重要的数据结构,它们都是List接口的实现类。理解这两者的区别对于优化程序性能至关重要。面试官询问这些知识点,旨在评估应聘者的理论基础和实践能力...

    比较Vector、ArrayList和hashtable hashmap

    - Vector 和 ArrayList 都实现了 List 接口,其中 Vector 是线程安全的,而 ArrayList 不是。ArrayList 在插入和查找性能上通常优于 Vector,因为 Vector 的同步操作会带来额外的性能开销。 - LinkedList 实现了 ...

    Map+List+ArrayList+LinkedList Java源码

    常见的List实现类有ArrayList和LinkedList。 **ArrayList类** `ArrayList`是基于数组实现的List,它提供了一个动态增长的数组来存储元素。由于其底层是数组,所以它的随机访问(通过索引)速度非常快。但是,插入和...

    Java 集合类(HashSet、ArrayList、LinkedList、HashMap).pptx

    掌握List集合、Set集合、Map集合的使用以及Iterator迭代器和foreach循环的使用 了解常用的集合类 熟悉泛型的使用

    【死磕Java集合】-集合源码分析.pdf

    Java集合框架源码分析 Java集合框架是Java语言中一个非常重要的组件,提供了多种数据结构和算法来存储和操作数据。在Java集合框架中,LinkedList、ArrayList、HashMap、TreeMap等都是非常常用的数据结构。本文将对...

    Java集合系列(LinkedHashMap+LinkedList+ArrayList)

    今天,我们将介绍 Java 集合系列中的三个重要成员:LinkedHashMap、LinkedList 和 ArrayList。 LinkedHashMap LinkedHashMap 是 Java 集合系列中的一种哈希表实现,继承自 HashMap。它的主要特点是可以维护元素的...

    集合框架学习笔记

    这篇学习笔记将深入探讨Java集合框架的基础概念、主要类库以及常见应用场景。 首先,Java集合框架分为两种基本类型:List(列表)和Set(集)。List接口代表有序的集合,允许重复元素,如ArrayList和LinkedList;而...

    Java集合框架常见面试题

    ArrayList、LinkedList 是 List 接口的两个主要实现类。 * Set:Set 接口继承自 Collection 接口,用于存储无序的、不可重复的元素。HashSet、LinkedHashSet 是 Set 接口的两个主要实现类。 * Map:Map 接口定义了...

    Java源码分析:集合-容器.pdf

    List接口有三种重要的实现类:ArrayList、LinkedList和Vector。ArrayList基于数组实现,它提供了动态数组的功能,具有高效的随机访问速度,但是它的插入和删除操作相对较慢。LinkedList基于双向链表实现,它具有高效...

    学士后Java集合框架和泛型课后习题答案

    在Java中,集合框架主要包括接口(如List、Set、Queue)和实现这些接口的类(如ArrayList、HashSet、LinkedList等)。这个框架允许我们高效地处理各种数据结构,而无需从头开始编写代码。泛型则是Java 5引入的一项...

    java集合类详解(set list ArrayList等java集合类详述)

    Java 集合框架中的实现类包括: * Set:HashSet、LinkedHashSet、TreeSet * List:ArrayList、LinkedList * Map:HashMap、TreeMap ArrayList 是一个可以自动增长容量的数组,我们可以将其看作是一个可以自动增长...

    Java集合框架常用集合源代码及其实现

    这个框架包括了多种类型的集合,如List、Set、Queue和Map,以及它们的各种实现类,如ArrayList、LinkedList、HashSet、HashMap等。下面将详细讲解这些集合及其源代码实现。 首先,`List`接口代表了一个有序的集合,...

    JAVA学习Java集合框架.pptx

    ArrayList和LinkedList是List的两个实现类,HashMap是Map的实现类。 集合的特点 Java集合框架的集合有以下特点: * 可以存储大量数据 * 可以动态改变大小 * 提供了多种集合操作 ArrayList的使用 ArrayList是...

    java集合框架全面进阶.pdf

    List有三个主要的实现类:ArrayList、LinkedList和Vector。ArrayList基于动态数组实现,适合随机访问元素;LinkedList基于链表实现,适合频繁的插入和删除操作;Vector是线程安全的,但在非多线程环境中效率比...

    Java集合框架详解

    集合框架是一个统一的数据结构模型,它定义了一系列接口,如Collection、List、Set和Map,以及它们的实现类,如ArrayList、LinkedList、HashSet、HashMap等。容器是这些接口和类的统称,它们用于存储和管理对象。...

    集合框架的总结

    本文将深入探讨集合框架的总结,重点关注其核心接口、类以及如何通过源码理解和利用这些工具。 首先,集合框架的基石是接口,主要包括`List`、`Set`和`Map`。`List`接口代表有序的集合,元素可以重复,如`ArrayList...

    基于JAVA集合框架及实用类实现的超市会员管理系统

    集合框架包括接口(如List、Set、Queue)和实现这些接口的具体类(如ArrayList、LinkedList、HashSet、HashMap等)。在这个会员管理系统中,可能使用ArrayList来存储会员信息,因为它的动态增长特性和随机访问效率高...

Global site tag (gtag.js) - Google Analytics