继续说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了,先祝自己生日快乐~~!!!