您好,登錄后才能下訂單哦!
這篇文章主要講解了“java中數組與鏈表的比較”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“java中數組與鏈表的比較”吧!
數組與鏈表的比較:
ArrayList:
LinkedList:
總結
數組通過下標訪問的話是O(1)
數組一旦聲明 長度就是固定的
數組的數據是物理邏輯均連續的
鏈表增刪要快一些, 數組遍歷快一些
長度一定的話, 數組的存儲空間比鏈表要小
ArrayList是List接口的實現類,它是支持根據需要而動態增長的數組;java中標準數組是定長的,在數組被創建之后,它們不能被加長或縮短。這就意味著在創建數組時需要知道數組的所需長度,但有時我們需要動態程序中獲取數組長度。ArrayList就是為此而生的。
擴容機制發生在add()方法調用的時候;
public boolean add(E e) { //擴容 ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
該行代碼ensureCapacityInternal()是用來擴用的,形參是最小擴容量,進入該方法后:
private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); }
通過方法calculateCapacity(elementData, minCapacity)獲取:
private static int calculateCapacity(Object[] elementData, int minCapacity) { //如果傳入的是個空數組則最小容量取默認容量與minCapacity之間的最大值 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; }
使用 ensureExplicitCapacity方法可以判斷是否需要擴容:
private void ensureExplicitCapacity(int minCapacity) { modCount++; // 如果最小需要空間比elementData的內存空間要大,則需要擴容 if (minCapacity - elementData.length > 0) //擴容 grow(minCapacity); }
需要擴容,進入ArrayList擴容的關鍵方法grow():擴大為原來的1.5倍;
private void grow(int minCapacity) { // 獲取到ArrayList中elementData數組的內存空間長度 int oldCapacity = elementData.length; // 擴容至原來的1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); // 再判斷一下新數組的容量夠不夠,夠了就直接使用這個長度創建新數組, // 不夠就將數組長度設置為需要的長度 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //若預設值大于默認的最大值檢查是否溢出 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // 調用Arrays.copyOf方法將elementData數組指向新的內存空間時newCapacity的連續空間 // 并將elementData的數據復制到新的內存空間 elementData = Arrays.copyOf(elementData, newCapacity); }
至此得出ArrayList擴容的本質是計算出新的擴容數組的size后實例化,并將原有數組內容復制到新數組中去。
鏈表實現擴容,直接在尾指針后面加入新的元素即可。
實現LinkedList:LinkedList的底層實現是鏈表。更深理解是一個雙向鏈表。
節點代碼:
//節點 public class Node { Node previous;//前繼,指向前一個Node Object data;//節點數據 Node next;//后繼,指向后一個Node public Node() { } public Node(Node previous, Object data, Node next) { super(); this.previous = previous; this.data = data; this.next = next; } }
初始化MyLinkedList:
public class MyLinkedList { private Node first;//首節點 private Node last;//尾節點 private int size;//鏈表大小 public MyLinkedList() { first = null; last = null; size = 0; } }
尾部添加,實現add(Object obj)方法:
public void add(Object obj){ Node node = new Node(null,null,null); if(first==null){//first=null,說明LinkedList中沒有一個節點 node.data = obj; first = node; last = node;//第一個節點和最后一個節點都是node size++; }else{ node.data = obj; last.next = node;//和最后一個連接起來 node.previous = last; last = node;//當前節點變為末尾節點 size++; }
現get(int index)方法,獲取index處的節點并返回Node:
使用循環,遍歷鏈表:
public Node get(int index) { RangeCheck(index); Node temp = null; if(index < (size>>1)){//改進的遍歷方法,右移運算符的巧用 temp = first; for(int i=0;i<index;i++){ temp = temp.next; } }else { temp = last; for(int i=size-1;i>index;i--){ temp = temp.previous; } } return temp; }
任意位置插入,實現add(int index,Object obj)方法:插入的步驟注意順序,不要產生斷鏈。
public void add(int index,Object obj) { RangeCheck(index);//對傳入的索引必須進行檢查,判斷是否越界 Node node = new Node(null,null,null); node.data = obj; Node node2=first; for(int i=0;i<index-1;i++){ node2 = node2.next; } node.next = node2.next; node2.next.previous=node; node2.next = node; node.previous=node2; size++; }
RangeCheck():
private void RangeCheck(int index) { if(index<0||index >= size){ throw new IndexOutOfBoundsException("IndexOutOfBounds"+index);//不合法則拋出異常 } }
實現remove(Object obj)方法:
public boolean remove(Object obj) { Node node = first; if(obj==null){ while(node!=null){ if(node.data==null){ removefast(node); return true; } node = node.next; } }else { while(node!=null){ if(obj.equals(node.data)){ removefast(node); return true; } node = node.next; } } return false; } private void removefast(Node node){ node.previous.next=node.next; size--; node.data=null; node.previous = node.next = null; }
實現set(int index,Object obj)方法:
public Object set(int index,Object obj) { Node node = get(index); Object oldObject=node.data; node.data = obj; return oldObject; }
感謝各位的閱讀,以上就是“java中數組與鏈表的比較”的內容了,經過本文的學習后,相信大家對java中數組與鏈表的比較這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。