摘要:源碼分析是一個(gè)雙向鏈表的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)。對(duì)于支持隨機(jī)訪問數(shù)據(jù)的比如數(shù)組,應(yīng)該優(yōu)先使用。一個(gè)有序的集合支持在頭和尾進(jìn)行插入和刪除元素。的大多實(shí)現(xiàn)元素?cái)?shù)量是沒有大小限制的。構(gòu)造方法第一個(gè)是一個(gè)空的構(gòu)造器,第二個(gè)構(gòu)造器調(diào)用了方法。
LinkedList源碼分析
LinkedList是一個(gè)雙向鏈表的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)。
類的實(shí)現(xiàn)接口及繼承父類public class LinkedListAbstractSequentiaListextends AbstractSequentialList implements List , Deque , Cloneable, java.io.Serializable
這個(gè)類提供了一個(gè)List接口實(shí)現(xiàn),為實(shí)現(xiàn)序列訪問的數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)提供了所需要的最小化接口實(shí)現(xiàn)。對(duì)于支持隨機(jī)訪問數(shù)據(jù)的List比如數(shù)組,應(yīng)該優(yōu)先使用AbstractList。
List 接口一個(gè)有序的集合。這個(gè)接口可以精確控制每個(gè)元素在列表中的位置插入。用戶可以通過整數(shù)索引來訪問元素(位置在列表中)。
Deque一個(gè)有序的集合支持在頭和尾進(jìn)行插入和刪除元素。deque是 double ended queue (雙端隊(duì)列)的縮寫。
deque的大多實(shí)現(xiàn)元素?cái)?shù)量是沒有大小限制的。但這個(gè)接口支持容量限制。
public LinkedList() { } public LinkedList(Collection extends E> c) { this(); addAll(c); }
第一個(gè)是一個(gè)空的構(gòu)造器,第二個(gè)構(gòu)造器調(diào)用了addAll()方法。
在研究addAll()方法之前,我們先來看一下幾個(gè)重要的屬性。
//容器的大小: transient int size = 0; //首節(jié)點(diǎn): transient Node常用方法解析 linkFirst() 插入第一個(gè)節(jié)點(diǎn)first; //尾節(jié)點(diǎn): transient Node last; //節(jié)點(diǎn)數(shù)據(jù)結(jié)構(gòu) private static class Node { E item;//節(jié)點(diǎn)的值 Node next;//節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn) 如果等于null 則為尾節(jié)點(diǎn) Node prev;//節(jié)點(diǎn)的上一個(gè)節(jié)點(diǎn),如果等于null則為首節(jié)點(diǎn) Node(Node prev, E element, Node next) {//構(gòu)造器 構(gòu)造節(jié)點(diǎn) this.item = element; this.next = next; this.prev = prev; } }
private void linkFirst(E e) { final NodelinkLast() 插入尾節(jié)點(diǎn)f = first;//獲得第一個(gè)節(jié)點(diǎn) final Node newNode = new Node<>(null, e, f);//構(gòu)造本次插入的首節(jié)點(diǎn),之前的首節(jié)點(diǎn)作為下一個(gè)節(jié)點(diǎn) first = newNode;//本次插入節(jié)點(diǎn)作為首節(jié)點(diǎn) if (f == null)//如果首節(jié)點(diǎn)為空,則尾節(jié)點(diǎn)也為他 last = newNode; else f.prev = newNode;//否則,之前的首節(jié)點(diǎn)作為新節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn) size++;//容器大小加一 modCount++;//修改次數(shù)加一 }
void linkLast(E e) { final NodelinkBefore(E e,Nodel = last;//獲取尾節(jié)點(diǎn) final Node newNode = new Node<>(l, e, null);//構(gòu)造新節(jié)點(diǎn) last = newNode;//本次插入節(jié)點(diǎn)為尾節(jié)點(diǎn) if (l == null)//如果尾節(jié)點(diǎn)為空 first = newNode;//則插入之前為空容器,首節(jié)點(diǎn)也為本次插入節(jié)點(diǎn) else l.next = newNode;//否則本次插入節(jié)點(diǎn)為之前尾節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn) size++;//容器大小加一 modCount++;//修改次數(shù)加一 }
//插入節(jié)點(diǎn)e ,在不為空的succ節(jié)點(diǎn)之前 void linkBefore(E e, NodeunlinkFirst(Nodesucc) { // assert succ != null; final Node pred = succ.prev;//succ的前一個(gè)節(jié)點(diǎn) final Node newNode = new Node<>(pred, e, succ);//構(gòu)造新節(jié)點(diǎn)插入succ之前 succ.prev = newNode;//succ的前一個(gè)節(jié)點(diǎn)為新構(gòu)造的節(jié)點(diǎn) if (pred == null)//如果succ的前一個(gè)節(jié)點(diǎn)為空,則本次插入節(jié)點(diǎn)將做為首節(jié)點(diǎn) first = newNode; else pred.next = newNode;//否則新節(jié)點(diǎn)作為succ的上一個(gè)節(jié)點(diǎn) size++;//容器大小加一 modCount++;//修改次數(shù)加一 }
private E unlinkFirst(Nodef) { // 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; }
f.next 釋放了內(nèi)存,等待垃圾回收機(jī)制進(jìn)行回收內(nèi)存。
//unlinkFirst方法被調(diào)用移除首節(jié)點(diǎn) public E removeFirst() { final NodeunlinkLast(Nodef = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); }
private E unlinkLast(NodegetFirst() 得到首節(jié)點(diǎn)的值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; } public E removeLast() { final Node l = last; if (l == null) throw new NoSuchElementException(); return unlinkLast(l); }
public E getFirst() { final Noderemove(Object o)f = first; if (f == null) throw new NoSuchElementException(); return f.item; }
public boolean remove(Object o) { if (o == null) {//如果被移除元素為空 for (Node隊(duì)列操作 peek() 返回隊(duì)列首元素,不移除x = first; x != null; x = x.next) { if (x.item == null) {//判斷節(jié)點(diǎn)的值是否為空 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; }
public E peek() { final Nodepoll() 返回隊(duì)列首元素,并移除隊(duì)列f = first; return (f == null) ? null : f.item; }
public E poll() { final Nodeoffer() 入隊(duì) 插入隊(duì)列尾f = first; return (f == null) ? null : unlinkFirst(f); }
public boolean offer(E e) { return add(e); }
從poll和offer方法可以看出Linked是一個(gè)FIFO先進(jìn)先出隊(duì)列(first input first output )
node(int index) 索引查詢元素//使用二分法用索引查找元素 Nodenode(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; }
}
關(guān)注我的公眾號(hào)第一時(shí)間閱讀有趣的技術(shù)故事
掃碼關(guān)注:
也可以在微信搜索公眾號(hào)即可關(guān)注我:codexiulian
渴望與你一起成長進(jìn)步!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/76917.html
摘要:介紹是線程不安全的,允許元素為的雙向鏈表。構(gòu)造方法共有兩個(gè)構(gòu)造方法,一個(gè)是創(chuàng)建一個(gè)空的構(gòu)造函數(shù),一個(gè)是將已有的添加到中。是將元素插入到的頭部。下一篇文章繼續(xù)分析上次分析了的結(jié)構(gòu)和添加方法這次開始分析下面的。注意源碼版本為直接進(jìn)入正題。 如果本文中有不正確的地方請指出由于沒有留言可以在公眾號(hào)添加我的好友共同討論。 1.介紹 LinkedList 是線程不安全的,允許元素為null的雙向鏈...
摘要:在次操作中其實(shí)即尾節(jié)點(diǎn)是共享資源,當(dāng)多個(gè)線程同時(shí)執(zhí)行此方法的時(shí)候,其實(shí)會(huì)出現(xiàn)線程安全問題。同樣會(huì)出現(xiàn)并發(fā)安全問題,下面對(duì)此問題進(jìn)行分析。 1.LinkedList源碼分析 LinkedList的是基于鏈表實(shí)現(xiàn)的java集合類,通過index插入到指定位置的時(shí)候使用LinkedList效率要比ArrayList高,以下源碼分析是基于JDK1.8. 1.1 類的繼承結(jié)構(gòu) LinkedLis...
摘要:它們會(huì)在鏈表為空時(shí),拋出獲取尾節(jié)點(diǎn)數(shù)據(jù)方法兩者區(qū)別方法在鏈表為空時(shí),會(huì)拋出,而則不會(huì),只是會(huì)返回。 目錄: 0-1. 簡介 0-2. 內(nèi)部結(jié)構(gòu)分析 0-3. LinkedList源碼分析 0-3-1. 構(gòu)造方法 0-3-2. 添加add方法 0-3-3. 根據(jù)位置取數(shù)據(jù)的方法 0-3-4. 根據(jù)對(duì)象得到索引的方法 0-3-5. 檢查鏈表是否包含某對(duì)象的方法 ...
摘要:表明該類是可以序列化的。與對(duì)比并沒有實(shí)現(xiàn),而實(shí)現(xiàn)表明其支持快速通常是固定時(shí)間隨機(jī)訪問。此接口的主要目的是允許一般的算法更改其行為,從而在將其應(yīng)用到隨機(jī)或連續(xù)訪問列表時(shí)能提供良好的性能。這是隨機(jī)訪問效率低的原因之一。指定節(jié)點(diǎn)不能為。 總覽 showImg(https://segmentfault.com/img/bVbsIzr?w=1007&h=600); 定義 public class...
摘要:一源碼分析本文分析雙向鏈表的查詢操作源碼實(shí)現(xiàn)。中源程序中,的查詢操作,通過函數(shù)實(shí)現(xiàn)。源程序中使用循環(huán)進(jìn)行遍歷。表示鏈表元素索引,初值為。針對(duì)空元素的情況,用循環(huán)遍歷,查找元素為的節(jié)點(diǎn),并返回索引。 一、contains源碼分析 本文分析雙向鏈表LinkedList的查詢操作源碼實(shí)現(xiàn)。jdk中源程序中,LinkedList的查詢操作,通過contains(Object o)函數(shù)實(shí)現(xiàn)。具體...
閱讀 1207·2021-09-03 10:44
閱讀 604·2019-08-30 13:13
閱讀 2796·2019-08-30 13:11
閱讀 1967·2019-08-30 12:59
閱讀 1034·2019-08-29 15:32
閱讀 1595·2019-08-29 15:25
閱讀 987·2019-08-29 12:24
閱讀 1277·2019-08-27 10:58