新聞中心
前言
日常開發(fā)中,集合是我們經(jīng)常用到的一種數(shù)據(jù)結(jié)構(gòu),當(dāng)然,集合也并不是一種,也沒有所謂的最好的集合,只有最適合的;

成都創(chuàng)新互聯(lián)是一家專注網(wǎng)站建設(shè)、網(wǎng)絡(luò)營(yíng)銷策劃、微信小程序定制開發(fā)、電子商務(wù)建設(shè)、網(wǎng)絡(luò)推廣、移動(dòng)互聯(lián)開發(fā)、研究、服務(wù)為一體的技術(shù)型公司。公司成立10年以來,已經(jīng)為上1000家成都純水機(jī)各業(yè)的企業(yè)公司提供互聯(lián)網(wǎng)服務(wù)?,F(xiàn)在,服務(wù)的上1000家客戶與我們一路同行,見證我們的成長(zhǎng);未來,我們一起分享成功的喜悅。
當(dāng)然作為高級(jí)程序員,我們不僅僅要會(huì)用,還要了解其中的原理;
今天我們就來聊聊LinkedList底層實(shí)現(xiàn)和原理
一、LinkedList介紹
- public class LinkedList
- extends AbstractSequentialList
- implements List
, Deque , Cloneable, java.io.Serializable - {
- //長(zhǎng)度
- transient int size = 0;
- //指向頭結(jié)點(diǎn)
- transient Node
first; - //指向尾結(jié)點(diǎn)
- transient Node
last; - }
1、LinkedList概述
LinkedList同時(shí)實(shí)現(xiàn)了List接口和Deque對(duì)口,也就是收它既可以看作一個(gè)順序容器,又可以看作一個(gè)隊(duì)列(Queue),同時(shí)又可以看作一個(gè)棧(stack);
這樣看來,linkedList簡(jiǎn)直就是無敵的,當(dāng)你需要使用棧或者隊(duì)列時(shí),可以考慮用LinkedList,一方面是因?yàn)镴ava官方已經(jīng)聲明不建議使用Stack類,更遺憾的是,Java里根本沒有一個(gè)叫做Queue的類(只是一個(gè)接口的名字);
關(guān)于?;蜿?duì)列,現(xiàn)在首選是ArrayDeque,它有著比LinkedList(當(dāng)作?;蜿?duì)列使用時(shí))更好的性能;
LinkedList的實(shí)現(xiàn)方式?jīng)Q定了所有跟下表有關(guān)的操作都是線性時(shí)間,而在首段或者末尾刪除元素只需要常數(shù)時(shí)間。為追求效率LinkedList沒有實(shí)現(xiàn)同步(synchronized),如果需要多個(gè)線程并發(fā)訪問,可以先采用Collections.synchronizedList()方法對(duì)其進(jìn)行包裝
2、數(shù)據(jù)結(jié)構(gòu)
繼承關(guān)系
- java.lang.Object
- java.util.AbstractCollection
- java.util.AbstractList
- java.util.AbstractSequentialList
- java.util.LinkedList
實(shí)現(xiàn)接口
- Serializable, Cloneable, Iterable
, Collection , Deque , List , Queue
基本屬性
- transient int size = 0; //LinkedList中存放的元素個(gè)數(shù)
- transient Node first; //頭節(jié)點(diǎn)
- transient Node last; //尾節(jié)點(diǎn)
- Collection 接口:Collection接口是所有集合類的根節(jié)點(diǎn),Collection表示一種規(guī)則,所有實(shí)現(xiàn)了Collection接口的類遵循這種規(guī)則
繼承的類與實(shí)現(xiàn)的接口
- List 接口:List是Collection的子接口,它是一個(gè)元素有序(按照插入的順序維護(hù)元素順序)、可重復(fù)、可以為null的集合
- AbstractCollection 類:Collection接口的骨架實(shí)現(xiàn)類,最小化實(shí)現(xiàn)了Collection接口所需要實(shí)現(xiàn)的工作量
- AbstractList 類:List接口的骨架實(shí)現(xiàn)類,最小化實(shí)現(xiàn)了List接口所需要實(shí)現(xiàn)的工作量
- Cloneable 接口:實(shí)現(xiàn)了該接口的類可以顯示的調(diào)用Object.clone()方法,合法的對(duì)該類實(shí)例進(jìn)行字段復(fù)制,如果沒有實(shí)現(xiàn)Cloneable接口的實(shí)例上調(diào)用Obejct.clone()方法,會(huì)拋出CloneNotSupportException異常。正常情況下,實(shí)現(xiàn)了Cloneable接口的類會(huì)以公共方法重寫Object.clone()
- Serializable 接口:實(shí)現(xiàn)了該接口標(biāo)示了類可以被序列化和反序列化,具體的 查詢序列化詳解
- Deque 接口:Deque定義了一個(gè)線性Collection,支持在兩端插入和刪除元素,Deque實(shí)際是“double ended queue(雙端隊(duì)列)”的簡(jiǎn)稱,大多數(shù)Deque接口的實(shí)現(xiàn)都不會(huì)限制元素的數(shù)量,但是這個(gè)隊(duì)列既支持有容量限制的實(shí)現(xiàn),也支持沒有容量限制的實(shí)現(xiàn),比如LinkedList就是有容量限制的實(shí)現(xiàn),其最大的容量為Integer.MAX_VALUE
- AbstractSequentialList 類:提供了List接口的骨干實(shí)現(xiàn),最大限度地減少了實(shí)現(xiàn)受“連續(xù)訪問”數(shù)據(jù)存儲(chǔ)(如鏈表)支持的此接口所需的工作,對(duì)于隨機(jī)訪問數(shù)據(jù)(如數(shù)組),應(yīng)該優(yōu)先使用 AbstractList,而不是使用AbstractSequentailList類
二、底層源碼分析
LinkedList是通過雙向鏈表去實(shí)現(xiàn)的,既然是鏈表實(shí)現(xiàn)那么它的隨機(jī)訪問效率比ArrayList要低,順序訪問的效率要比較的高。每個(gè)節(jié)點(diǎn)都有一個(gè)前驅(qū)(之前前面節(jié)點(diǎn)的指針)和一個(gè)后繼(指向后面節(jié)點(diǎn)的指針)
效果如下圖:
源碼標(biāo)注如下:
- public class LinkedList
extends AbstractSequentialList - implements List
, Deque , Cloneable, java.io.Serializable - {
- transient int size = 0; //LinkedList中存放的元素個(gè)數(shù)
- transient Node
first; //頭節(jié)點(diǎn) - transient Node
last; //尾節(jié)點(diǎn) - //構(gòu)造方法,創(chuàng)建一個(gè)空的列表
- public LinkedList() {
- }
- //將一個(gè)指定的集合添加到LinkedList中,先完成初始化,在調(diào)用添加操作
- public LinkedList(Collection extends E> c) {
- this();
- addAll(c);
- }
- //插入頭節(jié)點(diǎn)
- private void linkFirst(E e) {
- final Node
f = first; //將頭節(jié)點(diǎn)賦值給f節(jié)點(diǎn) - //new 一個(gè)新的節(jié)點(diǎn),此節(jié)點(diǎn)的data = e , pre = null , next - > f
- final Node
newNode = new Node<>(null, e, f); - first = newNode; //將新創(chuàng)建的節(jié)點(diǎn)地址復(fù)制給first
- if (f == null) //f == null,表示此時(shí)LinkedList為空
- last = newNode; //將新創(chuàng)建的節(jié)點(diǎn)賦值給last
- else
- f.prev = newNode; //否則f.前驅(qū)指向newNode
- size++;
- modCount++;
- }
- //插入尾節(jié)點(diǎn)
- void linkLast(E e) {
- final Node
l = last; - final Node
newNode = new Node<>(l, e, null); - last = newNode;
- if (l == null)
- first = newNode;
- else
- l.next = newNode;
- size++;
- modCount++;
- }
- //在succ節(jié)點(diǎn)前插入e節(jié)點(diǎn),并修改各個(gè)節(jié)點(diǎn)之間的前驅(qū)后繼
- void linkBefore(E e, Node
succ) { - // assert succ != null;
- final Node
pred = succ.prev; - final Node
newNode = new Node<>(pred, e, succ); - succ.prev = newNode;
- if (pred == null)
- first = newNode;
- else
- pred.next = newNode;
- size++;
- modCount++;
- }
- //刪除頭節(jié)點(diǎn)
- private E unlinkFirst(Node
f) { - // assert f == first && f != null;
- final E element = f.item;
- final Node
next = f.next; - f.item = null;
- f.next = null; // help GC
- first = next;
- if (next == null)
- last = null;
- else
- next.prev = null;
- size--;
- modCount++;
- return element;
- }
- //刪除尾節(jié)點(diǎn)
- private E unlinkLast(Node
l) { - // assert l == last && l != null;
- final E element = l.item;
- final Node
prev = l.prev; - l.item = null;
- l.prev = null; // help GC
- last = prev;
- if (prev == null)
- first = null;
- else
- prev.next = null;
- size--;
- modCount++;
- return element;
- }
- //刪除指定節(jié)點(diǎn)
- E unlink(Node
x) { - // assert x != null;
- final E element = x.item;
- final Node
next = x.next; //獲取指定節(jié)點(diǎn)的前驅(qū) - final Node
prev = x.prev; //獲取指定節(jié)點(diǎn)的后繼 - if (prev == null) {
- first = next; //如果前驅(qū)為null, 說明此節(jié)點(diǎn)為頭節(jié)點(diǎn)
- } else {
- prev.next = next; //前驅(qū)結(jié)點(diǎn)的后繼節(jié)點(diǎn)指向當(dāng)前節(jié)點(diǎn)的后繼節(jié)點(diǎn)
- x.prev = null; //當(dāng)前節(jié)點(diǎn)的前驅(qū)置空
- }
- if (next == null) { //如果當(dāng)前節(jié)點(diǎn)的后繼節(jié)點(diǎn)為null ,說明此節(jié)點(diǎn)為尾節(jié)點(diǎn)
- last = prev;
- } else {
- next.prev = prev; //當(dāng)前節(jié)點(diǎn)的后繼節(jié)點(diǎn)的前驅(qū)指向當(dāng)前節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)
- x.next = null; //當(dāng)前節(jié)點(diǎn)的后繼置空
- }
- x.item = null; //當(dāng)前節(jié)點(diǎn)的元素設(shè)置為null ,等待垃圾回收
- size--;
- modCount++;
- return element;
- }
- //獲取LinkedList中的第一個(gè)節(jié)點(diǎn)信息
- public E getFirst() {
- final Node
f = first; - if (f == null)
- throw new NoSuchElementException();
- return f.item;
- }
- //獲取LinkedList中的最后一個(gè)節(jié)點(diǎn)信息
- public E getLast() {
- final Node
l = last; - if (l == null)
- throw new NoSuchElementException();
- return l.item;
- }
- //刪除頭節(jié)點(diǎn)
- public E removeFirst() {
- final Node
f = first; - if (f == null)
- throw new NoSuchElementException();
- return unlinkFirst(f);
- }
- //刪除尾節(jié)點(diǎn)
- public E removeLast() {
- final Node
l = last; - if (l == null)
- throw new NoSuchElementException();
- return unlinkLast(l);
- }
- //將添加的元素設(shè)置為L(zhǎng)inkedList的頭節(jié)點(diǎn)
- public void addFirst(E e) {
- linkFirst(e);
- }
- //將添加的元素設(shè)置為L(zhǎng)inkedList的尾節(jié)點(diǎn)
- public void addLast(E e) {
- linkLast(e);
- }
- //判斷LinkedList是否包含指定的元素
- public boolean contains(Object o) {
- return indexOf(o) != -1;
- }
- //返回List中元素的數(shù)量
- public int size() {
- return size;
- }
- //在LinkedList的尾部添加元素
- public boolean add(E e) {
- linkLast(e);
- return true;
- }
- //刪除指定的元素
- public boolean remove(Object o) {
- if (o == null) {
- for (Node
x = first; x != null; x = x.next) { - if (x.item == null) {
- unlink(x);
- return true;
- }
- }
- } else {
- for (Node
x = first; x != null; x = x.next) { - if (o.equals(x.item)) {
- unlink(x);
- return true;
- }
- }
- }
- return false;
- }
- //將集合中的元素添加到List中
- public boolean addAll(Collection extends E> c) {
- return addAll(size, c);
- }
- //將集合中的元素全部插入到List中,并從指定的位置開始
- public boolean addAll(int index, Collection extends E> c) {
- checkPositionIndex(index);
- Object[] a = c.toArray(); //將集合轉(zhuǎn)化為數(shù)組
- int numNew = a.length; //獲取集合中元素的數(shù)量
- if (numNew == 0) //集合中沒有元素,返回false
- return false;
- Node
pred, succ; - if (index == size) {
- succ = null;
- pred = last;
- } else {
- succ = node(index); //獲取位置為index的結(jié)點(diǎn)元素,并賦值給succ
- pred = succ.prev;
- }
- for (Object o : a) { //遍歷數(shù)組進(jìn)行插入操作。修改節(jié)點(diǎn)的前驅(qū)后繼
- @SuppressWarnings("unchecked") E e = (E) o;
- Node
newNode = new Node<>(pred, e, null); - if (pred == null)
- first = newNode;
- else
- pred.next = newNode;
- pred = newNode;
- }
- if (succ == null) {
- last = pred;
- } else {
- pred.next = succ;
- succ.prev = pred;
- }
- size += numNew;
- modCount++;
- return true;
- }
- //刪除List中所有的元素
- public void clear() {
- // Clearing all of the links between nodes is "unnecessary", but:
- // - helps a generational GC if the discarded nodes inhabit
- // more than one generation
- // - is sure to free memory even if there is a reachable Iterator
- for (Node
x = first; x != null; ) { - Node
next = x.next; - x.item = null;
- x.next = null;
- x.prev = null;
- x = next;
- }
- first = last = null;
- size = 0;
- modCount++;
- }
- //獲取指定位置的元素
- public E get(int index) {
- checkElementIndex(index);
- return node(index).item;
- }
- //將節(jié)點(diǎn)防止在指定的位置
- public E set(int index, E element) {
- checkElementIndex(index);
- Node
x = node(index); - E oldVal = x.item;
- x.item = element;
- return oldVal;
- }
- //將節(jié)點(diǎn)放置在指定的位置
- public void add(int index, E element) {
- checkPositionIndex(index);
- if (index == size)
- linkLast(element);
- else
- linkBefore(element, node(index));
- }
- //刪除指定位置的元素
- public E remove(int index) {
- checkElementIndex(index);
- return unlink(node(index));
- }
- //判斷索引是否合法
- private boolean isElementIndex(int index) {
- return index >= 0 && index < size;
- }
- //判斷位置是否合法
- private boolean isPositionIndex(int index) {
- return index >= 0 && index <= size;
- }
- //索引溢出信息
- private String outOfBoundsMsg(int index) {
- return "Index: "+index+", Size: "+size;
- }
- //檢查節(jié)點(diǎn)是否合法
- private void checkElementIndex(int index) {
- if (!isElementIndex(index))
- throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
- }
- //檢查位置是否合法
- private void checkPositionIndex(int index) {
- if (!isPositionIndex(index))
- throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
- }
- //返回指定位置的節(jié)點(diǎn)信息
- //LinkedList無法隨機(jī)訪問,只能通過遍歷的方式找到相應(yīng)的節(jié)點(diǎn)
- //為了提高效率,當(dāng)前位置首先和元素?cái)?shù)量的中間位置開始判斷,小于中間位置,
- //從頭節(jié)點(diǎn)開始遍歷,大于中間位置從尾節(jié)點(diǎn)開始遍歷
- Node
node(int index) { - // assert isElementIndex(index);
- if (index < (size >> 1)) {
- Node
x = first; - for (int i = 0; i < index; i++)
- x = x.next;
- return x;
- } else {
- Node
x = last; - for (int i = size - 1; i > index; i--)
- x = x.prev;
- return x;
- }
- }
- //返回第一次出現(xiàn)指定元素的位置
- public int indexOf(Object o) {
- int index = 0;
- if (o == null) {
- for (Node
x = first; x != null; x = x.next) { - if (x.item == null)
- return index;
- index++;
- }
- } else {
- for (Node
x = first; x != null; x = x.next) { - if (o.equals(x.item))
- return index;
- index++;
- }
- }
- return -1;
- }
- //返回最后一次出現(xiàn)元素的位置
- public int lastIndexOf(Object o) {
- int index = size;
- if (o == null) {
- for (Node
x = last; x != null; x = x.prev) { - index--;
- if (x.item == null)
- return index;
- }
- } else {
- for (Node
x = last; x != null; x = x.prev) { - index--;
- if (o.equals(x.item))
- return index;
- }
- }
- return -1;
- }
- //彈出第一個(gè)元素的值
- public E peek() {
- final Node
f = first; - return (f == null) ? null : f.item;
- }
- //獲取第一個(gè)元素
- public E element() {
- return getFirst();
- }
- //彈出第一元素,并刪除
- public E poll() {
- final Node
f = first; - return (f == null) ? null : unlinkFirst(f);
- }
- //刪除第一個(gè)元素
- public E remove() {
- return removeFirst();
- }
- //添加到尾部
- public boolean offer(E e) {
- return add(e);
- }
- //添加到頭部
- public boolean offerFirst(E e) {
- addFirst(e);
- return true;
- }
- //插入到最后一個(gè)元素
- public boolean offerLast(E e) {
- addLast(e);
- return true;
- }
- //隊(duì)列操作
- //嘗試彈出第一個(gè)元素,但是不刪除元素
- public E peekFirst() {
- final Node
f = first; - return (f == null) ? null : f.item;
- }
- //隊(duì)列操作
- //嘗試彈出最后一個(gè)元素,不刪除
- public E peekLast() {
- final Node
l = last; - return (l == null) ? null : l.item;
- }
- //彈出第一個(gè)元素,并刪除
- public E pollFirst() {
- final Node
f = first; - return (f == null) ? null : unlinkFirst(f);
- }
- //彈出最后一個(gè)元素,并刪除
- public E pollLast() {
- final Node
l = last; - return (l == null) ? null : unlinkLast(l);
- }
- //如隊(duì)列,添加到頭部
- public void push(E e) {
- addFirst(e);
- }
- //出隊(duì)列刪除第一個(gè)節(jié)點(diǎn)
- public E pop() {
- return removeFirst();
- }
- //刪除指定元素第一次出現(xiàn)的位置
- public boolean removeFirstOccurrence(Object o) {
- return remove(o);
- }
- //刪除指定元素最后一次出現(xiàn)的位置
- public boolean removeLastOccurrence(Object o) {
- if (o == null) {
- for (Node
x = last; x != null; x = x.prev) { - if (x.item == null) {
- unlink(x);
- return true;
- }
- }
- } else {
- for (Node
x = last; x != null; x = x.prev) { -  
文章題目:數(shù)據(jù)結(jié)構(gòu)之LinkedList底層實(shí)現(xiàn)和原理詳解
本文來源:http://m.5511xx.com/article/cdicepo.html


咨詢
建站咨詢
