继续说List集合的另一个大头,LinkedList,首先我们先对它有个整体的了解,首先看这段代码:
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable
这里我们可以看出LinkedList实现了List和Deque接口,并且继承了AbstractSequentialList,这里知道LinkedList的底层实现其实是一个双向链表,并且通过实现List和Deque接口,可以被当做队列和堆栈进行操作。还实现了Serializable,因此可以支持序列化操作。好了老规矩,直接上源码,不过上源码之前先要知道几个关键:LinkedList包含两个重要的成员:header 和 size。
header是双向链表的表头,它是双向链表节点所对应的类Entry的实例。Entry中包含成员变量: previous, next, element。其中,previous是该节点的上一个节点,next是该节点的下一个节点,element是该节点所包含的值。
size是双向链表中节点的个数。
接下来是源码,源码总共分为三大部分,第一部分,一些常用API的实现:
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; } //创建一个新的LinkedList,包含集合c 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); } //判断是否包含元素o public boolean contains(Object o) { //调用的是indexof方法 return indexOf(o) != -1; } //返回LinkedList集合的元素个数 public int size() { return size; } //添加元素e到表头之前,此方法返回的是一个boolean型 public boolean add(E e) { addBefore(e, header); return true; } //从LinkedList中删除某元素,遍历链表,如果存在元素o就删除,jdk中分为了o等于null和不等于null两种 //遍历方法 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; } //从双向链表的末端将集合c添加到LinkedList中 public boolean addAll(Collection<? extends E> c) { return addAll(size, c); } //从双向链表的index索引位置将集合c添加进LinkedList 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++; //设置当前index节点的后一个节点 Entry<E> successor = (index==size ? header : entry(index)); //设置当前index节点的前一个节点 Entry<E> predecessor = successor.previous; //遍历链表,将集合c插入 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; } //清空链表 public void clear() { Entry<E> e = header.next; while (e != header) { Entry<E> next = e.next; //设置前一个节点为null e.next = e.previous = null; //设置当前节点为null e.element = null; //设置下一个节点为当前节点 e = next; } //初始化链表 header.next = header.previous = header; size = 0; modCount++; } //根据索引得到元素 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)); } //获取双向链表中指定位置的节点 private Entry<E> entry(int index) { if (index < 0 || index >= size) throw new IndexOutOfBoundsException("Index: "+index+ ", Size: "+size); Entry<E> e = header; //获取index处的节点,若index小于长度的1/2,并向下取整,则进行正向遍历,反之则反向遍历 //位运算比除法快, 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; } //从前开始遍历查找是否有值为o的元素,有的话返回索引值,没有的话返回-1 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; } //返回第一个节点若LinkedList大小为0则返回null public E peek() { if (size==0) return null; return getFirst(); } //返回第一个节点,若LinkedList大小为0则抛出异常 public E element() { return getFirst(); } //删除并返回第一个节点,若LinkedList大小为0则返回null public E poll() { if (size==0) return null; return removeFirst(); } //删除并返回第一个节点 public E remove() { return removeFirst(); } //将e添加到链表末尾 public boolean offer(E e) { return add(e); } //将e添加到链表开头 public boolean offerFirst(E e) { addFirst(e); return true; } //将e添加到双向链表末尾 public boolean offerLast(E e) { addLast(e); return true; } //返回第一个节点 public E peekFirst() { if (size==0) return null; return getFirst(); } //返回最后一个节点 public E peekLast() { if (size==0) return null; return getLast(); } //删除并返回最后一个节点 public E pollFirst() { if (size==0) return null; return removeFirst(); } //删除并返回最后一个节点 public E pollLast() { if (size==0) return null; return removeLast(); } //将e插入双向链表开头 public void push(E e) { addFirst(e); } //删除并返回第一个节点 public E pop() { return removeFirst(); } //将链表从前开始查找,如果有元素o,则删除 public boolean removeFirstOccurrence(Object o) { return remove(o); } //将链表从后开始查找,如果有元素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; }
第二部分,迭代器类listItr的实现,这个原理和我之前说的Iterator实现原理差不多。
// List迭代器 356 private class ListItr implements ListIterator<E> { 357 // 上一次返回的节点 358 private Entry<E> lastReturned = header; 359 // 下一个节点 360 private Entry<E> next; 361 // 下一个节点对应的索引值 362 private int nextIndex; 363 // 期望的改变计数。用来实现fail-fast机制。 364 private int expectedModCount = modCount; 365 366 // 构造函数。 367 // 从index位置开始进行迭代 368 ListItr(int index) { 369 // index的有效性处理 370 if (index < 0 || index > size) 371 throw new IndexOutOfBoundsException("Index: "+index+ ", Size: "+size); 372 // 若 “index 小于 ‘双向链表长度的一半’”,则从第一个元素开始往后查找; 373 // 否则,从最后一个元素往前查找。 374 if (index < (size >> 1)) { 375 next = header.next; 376 for (nextIndex=0; nextIndex<index; nextIndex++) 377 next = next.next; 378 } else { 379 next = header; 380 for (nextIndex=size; nextIndex>index; nextIndex--) 381 next = next.previous; 382 } 383 } 384 385 // 是否存在下一个元素 386 public boolean hasNext() { 387 // 通过元素索引是否等于“双向链表大小”来判断是否达到最后。 388 return nextIndex != size; 389 } 390 391 // 获取下一个元素 392 public E next() { 393 checkForComodification(); 394 if (nextIndex == size) 395 throw new NoSuchElementException(); 396 397 lastReturned = next; 398 // next指向链表的下一个元素 399 next = next.next; 400 nextIndex++; 401 return lastReturned.element; 402 } 403 404 // 是否存在上一个元素 405 public boolean hasPrevious() { 406 // 通过元素索引是否等于0,来判断是否达到开头。 407 return nextIndex != 0; 408 } 409 410 // 获取上一个元素 411 public E previous() { 412 if (nextIndex == 0) 413 throw new NoSuchElementException(); 414 415 // next指向链表的上一个元素 416 lastReturned = next = next.previous; 417 nextIndex--; 418 checkForComodification(); 419 return lastReturned.element; 420 } 421 422 // 获取下一个元素的索引 423 public int nextIndex() { 424 return nextIndex; 425 } 426 427 // 获取上一个元素的索引 428 public int previousIndex() { 429 return nextIndex-1; 430 } 431 432 // 删除当前元素。 433 // 删除双向链表中的当前节点 434 public void remove() { 435 checkForComodification(); 436 Entry<E> lastNext = lastReturned.next; 437 try { 438 LinkedList.this.remove(lastReturned); 439 } catch (NoSuchElementException e) { 440 throw new IllegalStateException(); 441 } 442 if (next==lastReturned) 443 next = lastNext; 444 else 445 nextIndex--; 446 lastReturned = header; 447 expectedModCount++; 448 } 449 450 // 设置当前节点为e 451 public void set(E e) { 452 if (lastReturned == header) 453 throw new IllegalStateException(); 454 checkForComodification(); 455 lastReturned.element = e; 456 } 457 458 // 将e添加到当前节点的前面 459 public void add(E e) { 460 checkForComodification(); 461 lastReturned = header; 462 addBefore(e, next); 463 nextIndex++; 464 expectedModCount++; 465 } 466 467 // 判断 “modCount和expectedModCount是否相等” 468 final void checkForComodification() { 469 if (modCount != expectedModCount) 470 throw new ConcurrentModificationException(); 471 } 472 }
第三部分,双向链表节点的数据结构的实现:
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; } } //将节点(数据是e)添加到节点entry之前 private Entry<E> addBefore(E e, Entry<E> entry) { //新建一个newEntry节点 Entry<E> newEntry = new Entry<E>(e, entry, entry.previous); newEntry.previous.next = newEntry; newEntry.next.previous = newEntry; //改变linkedList长度 size++; modCount++; return newEntry; } //将节点e从链表中删除 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; }
最后还有一部分是像clone方法,序列化的实现等操作,就不详细分析了。
( 1 )大家可以看到相比ArrayList,LinkedList显然复杂了许多,而且API定义了操作失败时两种形式的输出,一种是抛出异常,一种是返回null或false.
看下表:
第一个元素(头部) 最后一个元素(尾部) 抛出异常 特殊值 抛出异常 特殊值 插入 addFirst(e) offerFirst(e) addLast(e) offerLast(e) 移除 removeFirst() pollFirst() removeLast() pollLast() 检查 getFirst() peekFirst() getLast() peekLast()
( 2 )LinkedList包含了Entry这个最重要的内部类,这是链表数据结构的核心实现,主要通过三个变量,next,previous,element来实现。
大概先分析这么多,10点从张家界陪爹娘回来就赶紧码了一篇出来,不知不觉都快5.4了,先祝自己生日快乐~~!!!