LinkedList使用链表结构实现(jdk1.6之前包括jdk1.6使用双向循环链表,自1.7开始使用双向链表)。
链表的添加节点与删除节点花费的时间要远比数组小,因为链表只涉及插入位置的两个节点的变动。
但是链表的查询却是需要遍历查询,花费的时间要比数组更多。
package cn.yangwanhao.collection.list; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.NoSuchElementException; /** * Title: MyLinkedList类<br> * Description: 模仿LinkedList和Iterator * Company: 卓瀛工作室 * * @author 杨万浩 * @version 1.0 */ public class MyLinkedList<E> implements Iterable<E> { /** * 集合的大小 */ private int theSize; /** * 集合变动的次数 */ private int modCount = 0; /** * 集合的头 */ private Node<E> beginMarker; /** * 集合的尾 */ private Node<E> endMarker; public MyLinkedList() { doClear(); } public void clear() { doClear(); } /** * 初始化集合 */ private void doClear() { // 初始化链表头部 beginMarker = new Node<E>(null, null, null); // 初始化链表尾部 endMarker = new Node<E>(null, beginMarker, null); // 因为一开始endMarker还没初始化,所以beginMarker的next为null,此时将beginMarker的next指向endMarker beginMarker.next = endMarker; // 初始化集合的大小为0 theSize = 0; modCount++; } public int size() { return theSize; } public boolean isEmpty() { return size() == 0; } public boolean add(E data) { add(size(), data); return true; } public void add(int idx, E data) { addBefore(getNode(idx, 0, size()), data); } /** * 在节点之前插入一条数据 * @param p 指定在哪个节点之前插入数据 * @param data 要插入的数据 */ private void addBefore(Node<E> p, E data) { // 创建一个node对象,它的next为传入的那个节点 // 即要在它之前插入,所以插入后新节点的next是p,previous是p的上一个节点 Node<E> newNode = new Node<E>(data, p.previous, p); // 把新节点的上一个节点的尾节点指向新节点 newNode.previous.next = newNode; // 把指定节点的上一个节点换成新节点 p.previous = newNode; // 长度和操作次数+1 theSize++; modCount++; } public E get(int idx) { return getNode(idx).data; } public E set(int idx, E newVal) { // 通过下标得到指定的节点 Node<E> p = getNode(idx); // 得到旧的数据 E oldVal = p.data; // 把新的数据赋值给该节点的数据 p.data = newVal; return oldVal; } public E remove(int idx) { return remove(getNode(idx)); } /** * 删除指定的节点 * @param p 要删除的节点 * @return 被删除的节点的数据 */ private E remove(Node<E> p) { //把下一个节点的头结点指向上一个节点 p.next.previous = p.previous; //把上一个节点的尾节点指向下一个节点 p.previous.next = p.next; //长度-1,操作次数+1 theSize--; modCount++; return p.data; } private Node<E> getNode(int idx) { return getNode(idx, 0, size()-1); } private Node<E> getNode(int idx, int lower, int upper) { Node<E> p; if(idx < lower || idx > upper) { throw new IndexOutOfBoundsException(); } //如果索引的位置在表的前半部分,那么从前往后遍历,否则从后往前遍历 if(idx < (size()>>1)) { p = beginMarker.next; for (int i = 0; i < idx; i++) { p = p.next; } } else { p = endMarker; for (int i = size(); i > idx; i--) { p = p.previous; } } return p; } @Override public Iterator<E> iterator() { return new MyLinkedListIterator(); } private static class Node<E> { public E data; public Node<E> previous; public Node<E> next; public Node(E data, Node<E> previous, Node<E> next) { this.data = data; this.previous = previous; this.next = next; } } private class MyLinkedListIterator implements Iterator<E> { /** * 初始化头结点 */ private Node<E> current = beginMarker.next; private int expectModCount = modCount; private boolean okToRemove = false; @Override public boolean hasNext() { return current != endMarker; } @Override public E next() { if(modCount != expectModCount) { throw new ConcurrentModificationException(); } if(!hasNext()) { throw new NoSuchElementException(); } E nextItem = current.data; current = current.next; okToRemove = true; return nextItem; } @Override public void remove() { if(modCount != expectModCount) { throw new ConcurrentModificationException(); } if(!okToRemove) { throw new IllegalStateException(); } //指向next()方法后,指针已经指向下一个节点,所以要删除的节点是current的上一个节点 MyLinkedList.this.remove(current.previous); okToRemove = false; } } }