LinkedList理解

Deque接口
支持两端元素插入和移除的线性集合。

public interface Deque<E> extends Queue<E> {
	//插入此双端队列的前面
	void addFirst(E e);
	//插入此双端队列的末尾
	void addLast(E e);
	//在此deque的前面插入指定的元素
	boolean offerFirst(E e);
	boolean offerLast(E e);
	//检索并删除此deque的第一个元素。 
	E removeFirst();
	//检索并删除此deque的第一个元素,如果此deque为空,则返回 null 。 
	E pollFirst();
	//检索,但不删除,这个deque的第一个元素。
	E getFirst();
	//检索但不删除由此deque表示的队列的头部(换句话说,此deque的第一个元素),如果此deque为空,则返回 null 。
	E peekFirst();
	//从此deque中删除指定元素的第一个出现。
	boolean removeFirstOccurrence(Object o);
	//将元素推送到由此deque表示的堆栈first
	void push(E e);
	//从这个deque表示的堆栈中弹出一个元素。 first
	E pop();
}

AbstractSequentialList抽象类
对AbstractList中的方法进行了进一步构造,主要是对ListIterator迭代

public abstract class AbstractSequentialList<E> extends AbstractList<E> {
 	add()
 	remove()
 	get()
 	set()
}

LinkedList类
特点

  • 随机访问效率低,因为每查找一个节点都要遍历一次
  • 双向链表,可作为队列和栈
  • 线程不安全
  • 元素可为null
  • 增删快,查找慢

链表中节点的定义

private static class Node<E> {
       E item;
       Node<E> next;
       Node<E> prev;

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

链表中的迭代器

private class ListItr implements ListIterator<E> {
		//next的返回节点
        private Node<E> lastReturned;
        //下一节点
        private Node<E> next;
        //下一节点索引
        private int nextIndex;
        //结构修改次数
        private int expectedModCount = modCount;
		//返回指定位置的节点
		ListItr(int index) {
            next = (index == size) ? null : node(index);
            nextIndex = index;
        }

		public E next() {
            checkForComodification();
            if (!hasNext())
                throw new NoSuchElementException();
            lastReturned = next;
            next = next.next;
            nextIndex++;
            return lastReturned.item;
        }

		public void remove() {
            checkForComodification();
            if (lastReturned == null)
                throw new IllegalStateException();
			//删除节点的下一节点
            Node<E> lastNext = lastReturned.next;
            //将节点从链表中删除,modCount++
            unlink(lastReturned);
            //如果next=删除节点则next后移
            if (next == lastReturned)
                next = lastNext;
            else
                nextIndex--;
            lastReturned = null;
            expectedModCount++;
        }
}

成员变量

//链表大小
transient int size = 0;
//链表第一个节点
transient Node<E> first;
//链表最后一个节点
transient Node<E> last;

主要方法

  • 将节点从当前链表除去
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;
        }
		//节点值置null,返回删除的元素
        x.item = null;
        size--;
        modCount++;
        return element;
}
  • 搜索返回指定位置的节点
Node<E> node(int index) {
	//如果输入位置在前半部分则从前开始遍历next
	//如果输入位置在后半部分则从后开始遍历prev
    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;
    }
}
  • 插入
public boolean add(E e) {
    linkLast(e);//在链表末尾插入元素
    return true;
}
public void add(int index, E element) {
    checkPositionIndex(index);
    //插入末尾
    if (index == size)
        linkLast(element);
    //找到index位置的节点,然后在节点前插入
    else
        linkBefore(element, node(index));
}
//在链表最后插入
void linkLast(E e) {
    final Node<E> l = last;
    //new新节点,初始prev为last
    final Node<E> newNode = new Node<>(l, e, null);
    last = newNode;
    //prev节点的next链接新节点
    if (l == null)
        first = newNode;
    else
        l.next = newNode;
    size++;
    modCount++;
}
//在某个节点前插入
void linkBefore(E e, Node<E> succ) {
    final Node<E> pred = succ.prev;
    //new新节点,初始prev为succ的prev,next为succ
    final Node<E> newNode = new Node<>(pred, e, succ);
    succ.prev = newNode;
    //prev节点的next链接新节点
    if (pred == null)
        first = newNode;
    else
        pred.next = newNode;
    size++;
    modCount++;
}

offerFirst->addFirst->linkFirst将元素添加都链表首位
  • 删除
//默认删除first
public E remove() {
    return removeFirst();
}
//遍历删除指定元素
public boolean remove(Object o) {
    if (o == null) {
        for (Node<E> x = first; x != null; x = x.next) {
            if (x.item == null) {
                unlink(x);
                return true;
            }
        }
    } else {
        for (Node<E> x = first; x != null; x = x.next) {
            if (o.equals(x.item)) {
                unlink(x);
                return true;
            }
        }
    }
    return false;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值