日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java linkedlist源码_Java集合之LinkedList源码分析

發(fā)布時間:2024/10/6 java 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java linkedlist源码_Java集合之LinkedList源码分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、LinkedList簡介

LinkedList是一種可以在任何位置進(jìn)行高效地插入和移除操作的有序序列,它是基于雙向鏈表實(shí)現(xiàn)的。

ps:這里有一個問題,就是關(guān)于實(shí)現(xiàn)LinkedList的數(shù)據(jù)結(jié)構(gòu)是否為循環(huán)的雙向鏈表,上網(wǎng)搜了有很多文章都說是循環(huán)的,并且有的文章中但是我看了源代碼覺得應(yīng)該不是循環(huán)的?

例如在刪除列表尾部節(jié)點(diǎn)的代碼:

private E unlinkLast(Nodel)

{

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;elseprev.next= null;

size--;

modCount++;returnelement;

}

這里刪除尾節(jié)點(diǎn)l后,將l前面的節(jié)點(diǎn)prev的next置為null,而并沒有指向head節(jié)點(diǎn)。不知道是不是因?yàn)榇a版本的原因(我的源代碼是在下載的jdk1.8.0_45文件中獲取的),如果讀者看到知道原因,希望能夠幫忙解答!

在源碼中定義了節(jié)點(diǎn)的基本結(jié)構(gòu):

private static class Node{

E item;//表示該節(jié)點(diǎn)包含的值

Node next; //表達(dá)當(dāng)前節(jié)點(diǎn)的下一個節(jié)點(diǎn)

Node prev; //表示當(dāng)前節(jié)點(diǎn)的上一個節(jié)點(diǎn)

Node(Node prev, E element, Nodenext) {this.item =element;this.next =next;this.prev =prev;

}

}

LinkedList的類圖如下所示:

LinkedList?是一個繼承于AbstractSequentialList的雙向鏈表。它也可以被當(dāng)作堆棧、隊(duì)列或雙端隊(duì)列進(jìn)行操作。

LinkedList?實(shí)現(xiàn)?List?接口,能對它進(jìn)行隊(duì)列操作。

LinkedList?實(shí)現(xiàn)?Deque?接口,即能將LinkedList當(dāng)作雙端隊(duì)列使用。

LinkedList?實(shí)現(xiàn)了Cloneable接口,即覆蓋了函數(shù)clone(),能克隆。

LinkedList?實(shí)現(xiàn)java.io.Serializable接口,這意味著LinkedList支持序列化,能通過序列化去傳輸。

LinkedList?是非同步的。

二、LinkedList源碼分析

1 public class LinkedList extends AbstractSequentialList implements List, Deque, Cloneable, java.io.Serializable2 {3 //實(shí)現(xiàn)Serilizable接口時,將不需要序列化的屬性前添加關(guān)鍵字transient,序列化對象的時候,這個屬性就不會序列化到指定的目的地中。

4 transient int size = 0;5 //指向首節(jié)點(diǎn)

6 transient Nodefirst;7 //指向最后一個節(jié)點(diǎn)

8 transient Nodelast;9 //構(gòu)建一個空列表

10 publicLinkedList() {11 }12 //構(gòu)建一個包含集合c的列表

13 public LinkedList(Collection extends E>c) {14 this();15 addAll(c);16 }17 //將節(jié)點(diǎn)值為e的節(jié)點(diǎn)作為首節(jié)點(diǎn)

18 private voidlinkFirst(E e) {19 final Node f =first;20 //構(gòu)建一個prev值為null,next為f,節(jié)點(diǎn)值為e的節(jié)點(diǎn)

21 final Node newNode = new Node<>(null, e, f);22 //將newNode作為首節(jié)點(diǎn)

23 first =newNode;24 //如果newNode后面沒有節(jié)點(diǎn)就將newNode作為最后一個節(jié)點(diǎn)

25 if (f == null)26 last =newNode;27 //否則就將newNode賦給其prev

28 else

29 f.prev =newNode;30 //列表長度加一

31 size++;32 modCount++;33 }34 //將節(jié)點(diǎn)值為e的節(jié)點(diǎn)作為最后一個節(jié)點(diǎn)

35 voidlinkLast(E e) {36 final Node l =last;37 //構(gòu)建一個prev值為l,next為null,節(jié)點(diǎn)值為e的節(jié)點(diǎn)

38 final Node newNode = new Node<>(l, e, null);39 last =newNode;40 if (l == null)41 first =newNode;42 else

43 l.next =newNode;44 size++;45 modCount++;46 }47 //在非空節(jié)點(diǎn)succ之前插入節(jié)點(diǎn)e

48 void linkBefore(E e, Nodesucc) {49 final Node pred =succ.prev;50 //將succ前面的節(jié)點(diǎn)和succ作為其prev和next

51 final Node newNode = new Node<>(pred, e, succ);52 //然后將newNode作為succ的prev

53 succ.prev =newNode;54 //如果原來succ是首節(jié)點(diǎn),則將newNode設(shè)置為首節(jié)點(diǎn)

55 if (pred == null)56 first =newNode;57 else

58 pred.next =newNode;59 size++;60 modCount++;61 }62 //釋放非空的首節(jié)點(diǎn)f

63 private E unlinkFirst(Nodef) {64 final E element =f.item;65 final Node next =f.next;66 f.item = null;67 f.next = null; //help GC68 //將first節(jié)點(diǎn)后面的節(jié)點(diǎn)設(shè)為首節(jié)點(diǎn)

69 first =next;70 if (next == null)71 last = null;72 else

73 next.prev = null;74 size--;75 modCount++;76 returnelement;77 }78 //釋放非空的尾節(jié)點(diǎn)l

79 private E unlinkLast(Nodel) {80 final E element =l.item;81 final Node prev =l.prev;82 l.item = null;83 l.prev = null; //help GC

84 last =prev;85 if (prev == null)86 first = null;87 else

88 prev.next = null;89 size--;90 modCount++;91 returnelement;92 }93 //刪除非空節(jié)點(diǎn)x

94 E unlink(Nodex)95 {96 final E element =x.item;97 final Node next = x.next; //x后面的節(jié)點(diǎn)

98 final Node prev = x.prev; //x前面的節(jié)點(diǎn)

99

100 if (prev == null) {101 first =next;102 } else{103 prev.next =next;104 x.prev = null;105 }106 if (next == null) {107 last =prev;108 } else{109 next.prev =prev;110 x.next = null;111 }112 x.item = null;113 size--;114 modCount++;115 returnelement;116 }117 //返回列表首節(jié)點(diǎn)元素值

118 publicE getFirst() {119 final Node f =first;120 if (f == null)121 throw newNoSuchElementException();122 returnf.item;123 }124 //返列表尾節(jié)點(diǎn)元素值

125 publicE getLast() {126 final Node l =last;127 if (l == null)128 throw newNoSuchElementException();129 returnl.item;130 }131 //移除首節(jié)點(diǎn)

132 publicE removeFirst() {133 final Node f =first;134 if (f == null)135 throw newNoSuchElementException();136 returnunlinkFirst(f);137 }138 //刪除尾節(jié)點(diǎn)

139 publicE removeLast() {140 final Node l =last;141 if (l == null)142 throw newNoSuchElementException();143 returnunlinkLast(l);144 }145 //在列表首部插入節(jié)點(diǎn)e

146 public voidaddFirst(E e) {147 linkFirst(e);148 }149 //在列表尾部插入節(jié)點(diǎn)e

150 public voidaddLast(E e) {151 linkLast(e);152 }153 //判斷列表中是否包含有元素o

154 public booleancontains(Object o) {155 return indexOf(o) != -1;156 }157 //返回列表長度大小

158 public intsize() {159 returnsize;160 }161 //在列表尾部插入元素

162 public booleanadd(E e) {163 linkLast(e);164 return true;165 }166 //刪除元素為o的節(jié)點(diǎn)

167 public booleanremove(Object o)168 {169 if (o == null) {170 for (Node x = first; x != null; x =x.next) {171 if (x.item == null) {172 unlink(x);173 return true;174 }175 }176 } else{177 for (Node x = first; x != null; x =x.next) {178 if(o.equals(x.item)) {179 unlink(x);180 return true;181 }182 }183 }184 return false;185 }186 //將集合c中所有元素添加到列表的尾部

187 public boolean addAll(Collection extends E>c) {188 returnaddAll(size, c);189 }190 //從指定的位置index開始,將集合c中的元素插入到列表中

191 public boolean addAll(int index, Collection extends E>c) {192 //首先判斷插入位置的合法性

193 checkPositionIndex(index);194 Object[] a =c.toArray();195 int numNew =a.length;196 if (numNew == 0)197 return false;198 Nodepred, succ;199 if (index == size) {//說明在列表尾部插入集合元素

200 succ = null;201 pred =last;202 }203 else { //否則,找到index所在的節(jié)點(diǎn)

204 succ =node(index);205 pred =succ.prev;206 }207 for(Object o : a) {208 @SuppressWarnings("unchecked") E e =(E) o;209 Node newNode = new Node<>(pred, e, null);210 if (pred == null)211 first =newNode;212 else

213 pred.next =newNode;214 pred =newNode;215 }216 if (succ == null) {217 last =pred;218 } else{219 pred.next =succ;220 succ.prev =pred;221 }222 size +=numNew;223 modCount++;224 return true;225 }226 //刪除列表中所有節(jié)點(diǎn)

227 public voidclear() {228 for (Node x = first; x != null; )229 {230 Node next =x.next;231 x.item = null;232 x.next = null;233 x.prev = null;234 x =next;235 }236 first = last = null;237 size = 0;238 modCount++;239 }240 //獲取指定索引位置節(jié)點(diǎn)的元素值

241 public E get(intindex) {242 checkElementIndex(index);243 returnnode(index).item;244 }245 //替換指定索引位置節(jié)點(diǎn)的元素值

246 public E set(intindex, E element) {247 checkElementIndex(index);248 Node x =node(index);249 E oldVal =x.item;250 x.item =element;251 returnoldVal;252 }253 //在指定索引位置之前插入元素e

254 public void add(intindex, E element) {255 checkPositionIndex(index);256 if (index ==size)257 linkLast(element);258 else

259 linkBefore(element, node(index));260 }261 //刪除指定位置的元素

262 public E remove(intindex) {263 checkElementIndex(index);264 returnunlink(node(index));265 }266 //判斷指定索引位置的元素是否存在

267 private boolean isElementIndex(intindex) {268 return index >= 0 && index = 0 && index <=size;272 }273 //構(gòu)建 IndexOutOfBoundsException詳細(xì)信息

274 private String outOfBoundsMsg(intindex) {275 return "Index: "+index+", Size: "+size;276 }277 private void checkElementIndex(intindex) {278 if (!isElementIndex(index))279 throw newIndexOutOfBoundsException(outOfBoundsMsg(index));280 }281 private void checkPositionIndex(intindex) {282 if (!isPositionIndex(index))283 throw newIndexOutOfBoundsException(outOfBoundsMsg(index));284 }285 //返回指定索引位置的節(jié)點(diǎn)

286 Node node(intindex) {287 //此處是一個小技巧,當(dāng)index

288 if (index < (size >> 1)) {289 Node x =first;290 for (int i = 0; i < index; i++)291 x =x.next;292 returnx;293 } else{294 Node x =last;295 for (int i = size - 1; i > index; i--)296 x =x.prev;297 returnx;298 }299 }//返回列表中第一次出現(xiàn)o的位置,若不存在則返回-1

300 public intindexOf(Object o) {301 int index = 0;302 if (o == null) {303 for (Node x = first; x != null; x =x.next) {304 if (x.item == null)305 returnindex;306 index++;307 }308 } else{309 for (Node x = first; x != null; x =x.next) {310 if(o.equals(x.item))311 returnindex;312 index++;313 }314 }315 return -1;316 }317 //逆向搜索,返回第一出現(xiàn)o的位置,不存在則返回-1

318 public intlastIndexOf(Object o) {319 int index =size;320 if (o == null) {321 for (Node x = last; x != null; x =x.prev) {322 index--;323 if (x.item == null)324 returnindex;325 }326 } else{327 for (Node x = last; x != null; x =x.prev) {328 index--;329 if(o.equals(x.item))330 returnindex;331 }332 }333 return -1;334 }335 //獲取列表首節(jié)點(diǎn)元素值

336 publicE peek() {337 final Node f =first;338 return (f == null) ? null: f.item;339 }340

341 //獲取列表首節(jié)點(diǎn)元素值,若為空則拋異常

342 publicE element() {343 returngetFirst();344 }345 //檢索首節(jié)點(diǎn),若空則返回null,不為空則返回其元素值并刪除首節(jié)點(diǎn)

346 publicE poll() {347 final Node f =first;348 return (f == null) ? null: unlinkFirst(f);349 }350 //檢索首節(jié)點(diǎn),若空則拋異常,不為空則返回其元素值并刪除首節(jié)點(diǎn)

351 publicE remove() {352 returnremoveFirst();353 }354 //在列表尾部增加節(jié)點(diǎn)e

355 public booleanoffer(E e) {356 returnadd(e);357 }358 //在列表首部插入節(jié)點(diǎn)e

359 public booleanofferFirst(E e) {360 addFirst(e);361 return true;362 }363 //在列表尾部插入節(jié)點(diǎn)e

364 public booleanofferLast(E e) {365 addLast(e);366 return true;367 }368 publicE peekFirst() {369 final Node f =first;370 return (f == null) ? null: f.item;371 }372 //獲取列表尾節(jié)點(diǎn)元素值

373 publicE peekLast() {374 final Node l =last;375 return (l == null) ? null: l.item;376 }377 publicE pollFirst() {378 final Node f =first;379 return (f == null) ? null: unlinkFirst(f);380 }381 publicE pollLast() {382 final Node l =last;383 return (l == null) ? null: unlinkLast(l);384 }385 //入棧

386 public voidpush(E e)387 {388 addFirst(e);389 }390 //出棧

391 publicE pop() {392 returnremoveFirst();393 }394 //刪除列表中第一出現(xiàn)o的節(jié)點(diǎn)

395 public booleanremoveFirstOccurrence(Object o) {396 returnremove(o);397 }398 //逆向搜索,刪除第一次出現(xiàn)o的節(jié)點(diǎn)

399 public booleanremoveLastOccurrence(Object o) {400 if (o == null) {401 for (Node x = last; x != null; x =x.prev) {402 if (x.item == null) {403 unlink(x);404 return true;405 }406 }407 } else{408 for (Node x = last; x != null; x =x.prev) {409 if(o.equals(x.item)) {410 unlink(x);411 return true;412 }413 }414 }415 return false;416 }

三、關(guān)于LinkedList的幾點(diǎn)說明

1、注意源碼中的?Node node(int index)方法:

Node node(intindex)

{if (index < (size >> 1))

{

Node x =first;for (int i = 0; i < index; i++)

x=x.next;returnx;

}else{

Node x =last;for (int i = size - 1; i > index; i--)

x=x.prev;returnx;

}

}

該方法返回雙向鏈表中指定位置處的節(jié)點(diǎn),而鏈表中是沒有下標(biāo)索引的,要指定位置出的元素,就要遍歷該鏈表,從源碼的實(shí)現(xiàn)中,我們看到這里有一個加速動作。源碼中先將index與長度size的一半比較,如果indexsize/2,就只從位置size往前遍歷到位置index處。這樣可以減少一部分不必要的遍歷。

2、LinkedList與ArrayList的區(qū)別:

LinkedList與ArrayList在性能上各有優(yōu)缺點(diǎn),都有各自適用的地方,總結(jié)如下:

ArrayList是實(shí)現(xiàn)了基于動態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu),LinkedList基于鏈表的數(shù)據(jù)結(jié)構(gòu)。

LinkedList不支持高效的隨機(jī)元素訪問。

ArrayList的空間浪費(fèi)主要體現(xiàn)在在list列表的結(jié)尾預(yù)留一定的容量空間,而LinkedList的空間花費(fèi)則體現(xiàn)在它的每一個元素都需要消耗相當(dāng)?shù)目臻g,就存儲密度來說,ArrayList是優(yōu)于LinkedList的。

總之,當(dāng)操作是在一列數(shù)據(jù)的后面添加數(shù)據(jù)而不是在前面或中間,并且需要隨機(jī)地訪問其中的元素時,使用ArrayList會提供比較好的性能,當(dāng)你的操作是在一列數(shù)據(jù)的前面或中間添加或刪除數(shù)據(jù),并且按照順序訪問其中的元素時,就應(yīng)該使用LinkedList了。

3、LinkedList中允許元素為null

在查找和刪除時,源代碼如下所示:

public intindexOf(Object o) {int index = 0;if (o == null) {for (Node x = first; x != null; x =x.next) {if (x.item == null)returnindex;

index++;

}

}else{for (Node x = first; x != null; x =x.next) {if(o.equals(x.item))returnindex;

index++;

}

}return -1;

}

4、利用LinkedList實(shí)現(xiàn)棧操作

public class Stack{private LinkedListstack;//無參構(gòu)造函數(shù)

publicStack()

{

stack=new LinkedList();

}//構(gòu)造一個包含指定collection中所有元素的棧

public Stack(Collection extends T>c)

{

stack=new LinkedList(c);

}//入棧

public voidpush(T t)

{

stack.addFirst(t);

}//出棧

publicT pull()

{returnstack.remove();

}//棧是否為空

booleanisEmpty()

{returnstack.isEmpty();

}//打印棧元素

public voiddisplay()

{for(Object o:stack)

System.out.println(o);

}

}

5、LinkedList的基本用法:

總結(jié)

以上是生活随笔為你收集整理的java linkedlist源码_Java集合之LinkedList源码分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。