LinkedList源码分析

package com.mybatis.controller;


import java.util.*;
import java.util.function.Consumer;

/**
 * @创建人 yfc
 * @创建时间 2019-09-19 18:09
 * @描述 线程不安全的链表组成,双向链表,移动速度慢,插入速度快,查询效率低(采用折半方法,判断当前index是接近头部还是尾部,但是当数据量大的时候,效率依旧低)
 */
public class YLinkedList<E> extends AbstractSequentialList<E> implements List<E> {

	transient int size = 0;
	//指向第一个节点的指针
	transient Node<E> first;
	//指向最后一个节点的指针
	transient Node<E> last;


	public int size() {
		return size;
	}

	//新增节点
	public boolean add(E e) {
		linkLast(e);
		return true;
	}
	/**
	 * 链接E作为最后一个元素(尾插法,从尾部开始添加,hashmap中链表采用的是头插法)。
	 */
	void linkLast(E e) {
		//最后一个节点
		final Node<E> l = last;
		//当前节点(上一个节点为最后节点,下一个节点为null)
		final Node<E> newNode = new Node<>(l, e, null);
		//最后一个节点变为新增的这个节点
		last = newNode;
		//判断之前的尾节点是否为空,如果为空,第一个节点也为新增的节点,不为空,则为之前的尾节点加上下一个节点指针
		if (l == null)
			first = newNode;
		else
			l.next = newNode;
		//链表长度加1
		size++;
		modCount++;
	}


	/**
	 * 在此列表中的指定位置插入指定元素。将当前位于该位置的元素(如果有)和任何后续元素向右移动(在其索引中添加一个元素)
	 * element:新插入的元素
	 */
	public void add(int index, E element) {
		checkPositionIndex(index);

		//判断当前位置是不是最后一个
		if (index == size)
			linkLast(element);
		else
			//index位置上插入新的值
			linkBefore(element, node(index));
	}

	/**
	 * 返回指定元素索引处的(非空)节点。
	 */
	Node<E> node(int index) {
		// assert isElementIndex(index);
		//通过折半法快速定位到当前节点是靠近头还是靠近尾,减少一半计算量
		if (index < (size >> 1)) {
			Node<E> x = first;
			for (int i = 0; i < index; i++)
				x = x.next;
			return x;
		} else {
			Node<E> x = last;
			for (int i = size - 1; i > index; i--)
				x = x.prev;
			return x;
		}
	}
	/**
	 * 在非空节点成功之前插入元素e.
	 */
	void linkBefore(E e, Node<E> succ) {
		// assert succ != null;
		final Node<E> pred = succ.prev;
		//new一个新的节点,在index位置上插入新的节点,并将当前节点向后移一位
		final Node<E> newNode = new Node<>(pred, e, succ);
		succ.prev = newNode;
		if (pred == null)
			first = newNode;
		else
			pred.next = newNode;
		size++;
		modCount++;
	}


	private void checkPositionIndex(int index) {
		if (!isPositionIndex(index))
			throw new IndexOutOfBoundsException("索引下标越界");
	}


	/**
	 * 返回此列表中指定位置的元素。
	 */
	public E get(int index) {
		//检查索引是否存在
		checkElementIndex(index);
		return node(index).item;
	}

	/**
	 * 指示参数是否为现有元素的索引
	 */
	private void checkElementIndex(int index) {
		if (!isElementIndex(index))
			throw new IndexOutOfBoundsException("索引下标越界");
	}

	/**
	 * 指示参数是否为有效索引---(ps:这个方法同isPositionIndex功能一样,不知道JDK8为啥有这波操作)
	 */
	private boolean isElementIndex(int index) {
		return index >= 0 && index < size;
	}


	/**
	 * 判断当前索引是否有效
	 */
	private boolean isPositionIndex(int index) {
		return index >= 0 && index <= size;
	}

	/**
	 * 返回最后一个元素
	 */
	public E getLast() {
		final Node<E> l = last;
		if (l == null)
			throw new NoSuchElementException();
		return l.item;
	}

	/**
	 * 删除元素
	 */
	public E remove(int index) {
		checkElementIndex(index);
		return unlink(node(index));
	}

	/**
	 * 解除元素的关联
	 */
	E unlink(Node<E> x) {
		// assert x != null;
		final E element = x.item;
		//当前元素的下一个元素
		final Node<E> next = x.next;
		//当前元素的前一个元素
		final Node<E> prev = x.prev;

		//当前元素的前一个如果为空,说明当前是第一个元素,去除第一个元素,第一个元素的下一个元素向前移动
		if (prev == null) {
			first = next;
		} else {
			//前一个的下一个元素指向当前元素的下一个元素
			prev.next = next;
			x.prev = null;
		}

		if (next == null) {
			last = prev;
		} else {
			next.prev = prev;
			x.next = null;
		}

		x.item = null;
		size--;
		modCount++;
		return element;
	}

	//将链表转数组
	public Object[] toArray() {
		//定义一个size大的数组
		Object[] result = new Object[size];
		int i = 0;
		for (Node<E> x = first; x != null; x = x.next)
			result[i++] = x.item;
		return result;
	}

	//迭代器
	public ListIterator<E> listIterator(int index) {
		//检查index是否有效
		checkPositionIndex(index);
		return new ListItr(index);
	}

	//内部类
	private class ListItr implements ListIterator<E> {
		private Node<E> lastReturned;
		private Node<E> next;
		private int nextIndex;
		private int expectedModCount = modCount;

		ListItr(int index) {
			// 根据index定位到当前元素
			next = (index == size) ? null : node(index);
			nextIndex = index;
		}
		//eg:size 4,nextIndex 3   ()
		public boolean hasNext() {
			return nextIndex < size;
		}

		public E next() {
			checkForComodification();
			if (!hasNext())
				throw new NoSuchElementException();

			lastReturned = next;
			next = next.next;
			nextIndex++;
			return lastReturned.item;
		}

		public boolean hasPrevious() {
			return nextIndex > 0;
		}

		public E previous() {
			checkForComodification();
			if (!hasPrevious())
				throw new NoSuchElementException();

			lastReturned = next = (next == null) ? last : next.prev;
			nextIndex--;
			return lastReturned.item;
		}

		public int nextIndex() {
			return nextIndex;
		}

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

		public void remove() {
			checkForComodification();
			if (lastReturned == null)
				throw new IllegalStateException();

			Node<E> lastNext = lastReturned.next;
			//unlink(lastReturned);
			if (next == lastReturned)
				next = lastNext;
			else
				nextIndex--;
			lastReturned = null;
			expectedModCount++;
		}

		public void set(E e) {
			if (lastReturned == null)
				throw new IllegalStateException();
			checkForComodification();
			lastReturned.item = e;
		}

		public void add(E e) {
			checkForComodification();
			lastReturned = null;
			if (next == null)
				linkLast(e);
			else
				linkBefore(e, next);
			nextIndex++;
			expectedModCount++;
		}

		public void forEachRemaining(Consumer<? super E> action) {
			Objects.requireNonNull(action);
			while (modCount == expectedModCount && nextIndex < size) {
				action.accept(next.item);
				lastReturned = next;
				next = next.next;
				nextIndex++;
			}
			checkForComodification();
		}

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

	//内部类
	private static class Node<E> {
		//当前节点
		E item;
		//下一个节点
		YLinkedList.Node<E> next;
		//前一个节点
		YLinkedList.Node<E> prev;

		Node(YLinkedList.Node<E> prev, E element, YLinkedList.Node<E> next) {
			this.item = element;
			this.next = next;
			this.prev = prev;
		}
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值