参考文章:JCFInternals
环境:JDK1.9

介绍:
LinkedList同时实现了List接口和Deque接口,也就是说它既可以看作一个顺序容器,又可以看作一个队列(Queue),同时又可以看作一个栈(Stack),LinkedList底层通过双向链表实现,允许放入 null,未实现同步。

实现功能:

  • size():得到当前集合元素个数
  • isEmpty():判断集合是否为空
  • get(int index):获得指定位置集合
  • set(int index, T element):将指定位置集合设置为指定值
  • add(T element):向集合添加一个元素
  • add(int index, T element):向集合指定下标添加指定元素
  • remove(int index):移除指定下标的元素
  • remove(Object o):移除集合中第一次出现的指定元素

代码:

public class MyLinkedList<T> {

    int size;

    // 链表的第一个元素
    Node<T> first;

    // 链表的最后一个元素
    Node<T> last;

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    // 定义链表结点
    private static class Node<T> {
        T item;
        Node<T> prev;
        Node<T> next;

        public Node(Node<T> prev, T item, Node<T> next) {
            this.item = item;
            this.prev = prev;
            this.next = next;
        }
    }

    public boolean add(T element) {
        // 找到末尾指针
        final Node<T> l = last;
        final Node<T> newNode = new Node(l, element, null);
        last = newNode;
        // 如果当前链表为空,则 newNode 为第一个结点
        if (l == null) {
            first = newNode;
        } else {
            l.next = newNode;
        }
        size++;
        return true;
    }

    public void add(int index, T element) {
        // 范围检查
        checkPositionIndex(index);

        // 如果是最后一个插入
        if (index == size) {
            add(element);
        } else {
            // 找到 index 位置的链表
            final Node<T> cur = node(index);
            // 修改引用
            // 1. 要插入的新结点是 newNode
            // 2. newNode 的前一结点是 pred
            // 3. newNode 的后一结点是 cur
            final Node<T> pred = cur.prev;
            final Node<T> newNode = new Node(pred, element, cur);
            cur.prev = newNode;
            if (pred == null) {
                first = newNode;
            } else {
                pred.next = newNode;
            }
            size++;
        }
    }

    public boolean remove(Object o) {
        if (o == null) {
            for (Node<T> x = first; x != null; x = x.next) {
                if (x.item == null) {
                    // 删除该结点
                    unlink(x);
                    return true;
                }
            }
        } else {
            for (Node<T> x = first; x != null; x = x.next) {
                if (x.item.equals(o)) {
                    // 删除该结点
                    unlink(x);
                    return true;
                }
            }
        }
        return false;
    }

    public T remove(int index) {
        // 范围检查
        checkPositionIndex(index);
        return unlink(node(index));
    }

    public T get(int index) {
        // 范围检查
        checkPositionIndex(index);
        return node(index).item;
    }

    public T set(int index, T element) {
        // 范围检查
        checkPositionIndex(index);
        Node<T> x = node(index);
        T oldVal = x.item;
        x.item = element;
        return oldVal;
    }

    private T unlink(Node<T> x) {
        final T element = x.item;
        final Node<T> prev = x.prev;
        final Node<T> next = x.next;

        // 修改前一结点的指针
        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--;
        return element;
    }


    private Node<T> node(int index) {
        // 前一半
        if (index < (size >> 1)) {
            Node<T> x = first;
            for (int i = 0; i < index; i++) {
                x = x.next;
            }
            return x;
        } else {
            Node<T> x = last;
            for (int i = size - 1; i > index; i--) {
                x = x.prev;
            }
            return x;
        }
    }

    private boolean checkPositionIndex(int index) {
        if (index < 0 || index > size) {
            throw new RuntimeException("下标越界!");
        }
        return true;
    }
}