`

深入JDK源代码之LinkedList类

 
阅读更多
public class LinkedList<E>extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, SerializableList 

   接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。

    此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。
    所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。
   注意,此实现不是同步的。如果多个线程同时访问一个链接列表,而其中至少一个线程从结构上修改了该列表,则它必须 保持外部同步。(结构修改指添加或删除一个或多个元素的任何操作;仅设置元素的值不是结构修改。)这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,则应该使用 Collections.synchronizedList 方法来“包装”该列表。最好在创建时完成这一操作,以防止对列表进行意外的不同步访问,如下所示:

  
List list = Collections.synchronizedList(new LinkedList(...));

    此类的 iterator 和 listIterator 方法返回的迭代器是快速失败 的:在迭代器创建之后,如果从结构上对列表进行修改,除非通过迭代器自身的 remove 或 add 方法,其他任何时间任何方式的修改,迭代器都将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不冒将来不确定的时间任意发生不确定行为的风险。

    注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何硬性保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException。因此,编写依赖于此异常的程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测程序错误。

  一、JDK中LinkedList总体实现:Linked实际上是一个双向链表,链表的每个节点是一个Entry对象,而Entry对象有一个previous引用和next引用。LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将[color=red][b]链接列表用作堆栈、队列或双端队列。
 
 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;

	public LinkedList() {
		header.next = header.previous = header;
	}

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

	// 移除表头
	public E removeFirst() {
		return remove(header.next);
	}

	// 移除表尾
	public E removeLast() {
		return remove(header.previous);
	}

	// 在表头添加
	public void addFirst(E e) {
		addBefore(e, header.next);
	}

	// 在表尾添加
	public void addLast(E e) {
		addBefore(e, header);
	}

	public boolean contains(Object o) {
		return indexOf(o) != -1;
	}

	public int size() {
		return size;
	}

	// 将指定元素添加到此列表的结尾。
	public boolean add(E e) {
		addBefore(e, header);
		return true;
	}

	//从此列表中移除首次出现的指定元素(如果存在)。
	public boolean remove(Object o) {
		if (o == null) {
			for (Entry<E> e = header.next; e != header; e = e.next) {
				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;
	}
   //添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序。
	public boolean addAll(Collection<? extends E> c) {
		return addAll(size, c);
	}

	public boolean addAll(int index, Collection<? extends E> c) {
		if (index < 0 || index > size)
			throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
					+ size);
		Object[] a = c.toArray();
		int numNew = a.length;
		if (numNew == 0)
			return false;
		modCount++;

		Entry<E> successor = (index == size ? header : entry(index));
		Entry<E> predecessor = successor.previous;
		for (int i = 0; i < numNew; i++) {
			Entry<E> e = new Entry<E>((E) a[i], successor, predecessor);
			predecessor.next = e;
			predecessor = e;
		}
		successor.previous = predecessor;

		size += numNew;
		return true;
	}

	/**
	 * Removes all of the elements from this list.
	 */
	public void clear() {
		Entry<E> e = header.next;
		while (e != header) {
			Entry<E> next = e.next;
			e.next = e.previous = null;
			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;
	}

	public void add(int index, E element) {
		addBefore(element, (index == size ? header : entry(index)));
	}

	public E remove(int index) {
		return remove(entry(index));
	}

	/**
	 * Returns the indexed entry.
	 */
	private Entry<E> entry(int index) {
		if (index < 0 || index >= size)
			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;
		} else {
			for (int i = size; i > index; i--)
				e = e.previous;
		}
		return e;
	}

	public int indexOf(Object o) {
		int index = 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;
	}

	//从此列表中移除第一次出现的指定元素(从头部到尾部遍历列表时)。
	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;
	}
	
	public ListIterator<E> listIterator(int index) {
		return new ListItr(index);
	}
	private class ListItr implements ListIterator<E> {
		private Entry<E> lastReturned = header;
		private Entry<E> next;
		private int nextIndex;
		private int expectedModCount = modCount;

		ListItr(int index) {
			if (index < 0 || index > size)
				throw new IndexOutOfBoundsException("Index: " + index
						+ ", Size: " + size);
			if (index < (size >> 1)) {
				next = header.next;
				for (nextIndex = 0; nextIndex < index; nextIndex++)
					next = next.next;
			} else {
				next = header;
				for (nextIndex = size; nextIndex > index; nextIndex--)
					next = next.previous;
			}
		}

		public boolean hasNext() {
			return nextIndex != size;
		}

		public E next() {
			checkForComodification();
			if (nextIndex == size)
				throw new NoSuchElementException();

			lastReturned = next;
			next = next.next;
			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() {
			return nextIndex;
		}

		public int previousIndex() {
			return nextIndex - 1;
		}

		public void remove() {
			checkForComodification();
			Entry<E> lastNext = lastReturned.next;
			try {
				LinkedList.this.remove(lastReturned);
			} catch (NoSuchElementException e) {
				throw new IllegalStateException();
			}
			if (next == lastReturned)
				next = lastNext;
			else
				nextIndex--;
			lastReturned = header;
			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);
			nextIndex++;
			expectedModCount++;
		}

		final void checkForComodification() {
			if (modCount != expectedModCount)
				throw new ConcurrentModificationException();
		}
	}

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

	private Entry<E> addBefore(E e, Entry<E> entry) {
		Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
		newEntry.previous.next = newEntry;
		newEntry.next.previous = newEntry;
		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.next.previous = e.previous;
		e.next = e.previous = null;
		e.element = null;
		size--;
		modCount++;
		return result;
	}

	/**
	 * @since 1.6
	 */
	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();
		}
	}

	/**
	 * Returns a shallow copy of this <tt>LinkedList</tt>. (The elements
	 * themselves are not cloned.)
	 * 
	 * @return a shallow copy of this <tt>LinkedList</tt> instance
	 */
	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;

		// Initialize clone with our elements
		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];
		int i = 0;
		for (Entry<E> e = header.next; e != header; e = e.next)
			result[i++] = e.element;
		return result;
	}

	public <T> T[] toArray(T[] a) {
		if (a.length < 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)
			a[size] = null;

		return a;
	}

	private static final long serialVersionUID = 876323262645176354L;

	private void writeObject(java.io.ObjectOutputStream s)
			throws java.io.IOException {
		// Write out any hidden serialization magic
		s.defaultWriteObject();

		// Write out size
		s.writeInt(size);

		// Write out all elements in the proper order.
		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();

		// Read in size
		int size = s.readInt();

		// Initialize header
		header = new Entry<E>(null, null, null);
		header.next = header.previous = header;

		// Read in all elements in the proper order.
		for (int i = 0; i < size; i++)
			addBefore((E) s.readObject(), header);
	}
}


二、LinkedList实现的队列操作
// Queue operations.队列操作

	// 获取但不移除此列表的头(第一个元素)。
	public E peek() {
		if (size == 0)
			return null;
		return getFirst();
	}

	// 获取但不移除此列表的头(第一个元素)。
	public E element() {
		return getFirst();
	}

	//获取并移除此列表的头(第一个元素)
	public E poll() {
		if (size == 0)
			return null;
		return removeFirst();
	}

	// 获取并移除此列表的头(第一个元素)。
	public E remove() {
		return removeFirst();
	}

	//将指定元素添加到此列表的末尾(最后一个元素)。
	public boolean offer(E e) {
		return add(e);
	}

三、LinkedList实现的双端队列操作
// Deque operations //双端队列操作
	
	
	// 在此列表的开头插入指定的元素。
	public boolean offerFirst(E e) {
		addFirst(e);
		return true;
	}

	
	// 在此列表的末尾插入指定的元素。
	public boolean offerLast(E e) {
		addLast(e);
		return true;
	}

	// 获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
	public E peekFirst() {
		if (size == 0)
			return null;
		return getFirst();
	}

	// 获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
	public E peekLast() {
		if (size == 0)
			return null;
		return getLast();
	}

	// 获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
	public E pollFirst() {
		if (size == 0)
			return null;
		return removeFirst();
	}

	 //获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
	public E pollLast() {
		if (size == 0)
			return null;
		return removeLast();
	}
	

四、LinkedList实现的堆栈操作
//堆栈操作
	
	//入栈,将元素推入此列表所表示的堆栈。
	public void push(E e) {
		addFirst(e);
	}
    //出栈
	public E pop() {
		return removeFirst();
	}
0
5
分享到:
评论

相关推荐

    《Java 2 入门经典 JDK5》 源代码

    这个源代码在http://www.wrox.com上可以获得,并且还有课后习题的答案以及JDK5到JDK6的变动说明,甚至还有书中LinkedList类的纠正版本。(都在压缩包里的Beg_Java_15文件夹里) 但是为了学习JAVA我自己亲自把书上...

    java jdk实列宝典 光盘源代码

    java为数据结构中的列表定义了一个接口类java.util.list同时提供了3个实现类,分别是ArrayList、Vector、LinkedList使用; 生成不重复的随机数序列;列表、集合与数组的互相转换;java为数据结构中的映射定义一个接口...

    javajdk1.8源码-Java-source-reading:jdk1.8源代码分析

    近期计划:以jdk为主,java.lang和java.util下一些重要的类以及juc,将来可能会写web框架相关 jdk1.8 java.lang Integer String java.util Arrays ArrayList LinkedList HashMap HashSet LinkedHashMap

    java范例开发大全源代码

     11.3 Date类和Calendar类 324  实例191 使用Date类获取系统的当前时间 324  实例192 使用DateFormat类获取系统的当前时间 325  实例193 使用GregorianCalendar类获取系统的当前时间 326  实例194 使用...

    疯狂JAVA讲义

    1.5.1 编辑Java源代码 12 1.5.2 编译Java程序 13 学生提问:当我们使用编译C程序时,不仅需要指定存放目标文件的位置,也需要指定目标文件的文件名,这里使用javac编译Java程序时怎么不需要指定目标文件的文件名呢...

    从J2SE到J2EE知识点介绍

    (八) 复合自然主键实例(源代码hibernate_0500) 218 (九) Hibernate的类型 224 1. Java基本值类型的Hibernate映射 224 2. Java时间和日期类型的Hibernate映射类型 224 3. Java大对象类型的Hibernate映射类型 225 4....

    leetcode中文版-algorithm:leetcode一些示例代码

    的应用跟原理的掌握,这个我不推荐大家去读JDK的源代码, 里面具体的实现 其实涉及到生产实践中大量的改进,细节十分多,例如JDK8的HashMap 在达到8个hash冲突链表后会转成红黑树, 而在理论学习的阶

    java1.8源码-jdk1.8.0_151-:阅读Java源码,版本为jdk1.8.0_151,将会同步翻译源码中的文档注释

    作者现在大四快要毕业,在实习中,为了在未来成为一名架构师,下定决心开始读Java的源代码;读源码的过程非常难熬,我在以前也曾读过源码,但都坚持的不久,也没有细读。现在为了激励自己,也为了促使自己能够坚持...

    java8源码-source_code:源代码

    LinkedList手动实现(class:LinkedListByMe) 3. HashMap JDK1.7:(class:HashMapByMe7) 4. 枚举+lambda表达式(package:enums) 5. 测试io流(package:io) 6. Java8函数式编程(package:java8.function) 二、多线程 ...

    21天学通Java-由浅入深

    232 11.7 习题 232 第12章 内部类(精彩视频:71分钟) 234 12.1 非静态内部类 234 12.1.1 创建非静态内部类 234 12.1.2 在外部类中访问内部类 235 12.1.3 在外部类外访问内部类 236 12.1.4 在内部类中访问外部类 ...

    Java开发技术大全 电子版

    11.2.2链表(LinkedList)使用示例336 11.2.3优先队列(PriorityQueue)使用示例340 11.2.4哈希集合(HashSet)使用示例343 11.2.5哈希映射类(HashMap)使用示例347 11.2.6有序树(TreeSet)使用示例349 ...

    Java范例开发大全 (源程序)

     实例219 LinkedList的添加删除操作 395  实例220 运用Vector 397  实例221 改变Properties文件中的键值 399  第13章 多线程编程(教学视频:121分钟) 405  13.1 多线程的五种基本状态 405  实例222 ...

    Java范例开发大全(全书源程序)

    实例219 LinkedList的添加删除操作 395 实例220 运用Vector 397 实例221 改变Properties文件中的键值 399 第13章 多线程编程(教学视频:121分钟) 405 13.1 多线程的五种基本状态 405 实例222 启动线程 405 ...

    java范例开发大全

    实例278 通过指定的URL可以获取网页的源代码 542 实例279 一对多通信模式 544 实例280 自制浏览器 549 实例281 扫描TCP端口 551 实例282 TCP协议服务器 552 实例283 TCP协议客户机 553 实例284 Socket连接信息 555 ...

    java范例开发大全(pdf&源码)

    实例219 LinkedList的添加删除操作 395 实例220 运用Vector 397 实例221 改变Properties文件中的键值 399 第13章 多线程编程(教学视频:121分钟) 405 13.1 多线程的五种基本状态 405 实例222 启动线程 405 实例223...

    千方百计笔试题大全

    JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类? 17 69、文件读写的基本类 17 70、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 17 71、启动一个线程是用run()还是start()? ...

    java面试宝典

    JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类? 17 69、文件读写的基本类 17 70、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 17 71、启动一个线程是用run()还是start()? ...

    2017最新大数据架构师精英课程

    10_多线程-同步代码块-同步方法 11_多线程-生产消费问题 12_多线程-死锁问题 13_字符集问题' X4 e; v9 q' U2 W% f" l7 f$ F 14_String-StringBuffer-StringBuilder 15_集合-list-arrayList-linkedlist 16_集合-...

Global site tag (gtag.js) - Google Analytics