您好,登錄后才能下訂單哦!
本篇內容介紹了“LinkedList與ArrayList新增/刪除元素效率哪個更快”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
刪除元素和新增元素的原理是一樣的,所以刪除元素的操作和新增元素的操作耗時也是很相近
這里就不再贅述
測試結果非常明顯,對于 LinkedList 來說,如果使用 for 循環的話,效率特別低,但是 ArrayList 使用 for 循環去遍歷的話,就比較高
為啥呢?
emmm ,得從源碼說起
先來看 ArrayList 的源碼吧,這個比較簡單
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
能夠看到, ArrayList 實現了 List , RandomAccess , Cloneable 還有 Serializable 接口
你是不是對 RandomAccess 這個接口挺陌生的?這是個啥?
但是通過查閱源碼能夠發現它也只是個空的接口罷了,那 ArrayList 為啥還要去實現它嘞
因為 RandomAccess 接口是一個標志接口,它標識著“只要實現該接口的 list 類,都可以實現快速隨機訪問”
實現快速隨機訪問?你能想到什么?這不就是數組的特性嘛!可以直接通過 index 來快速定位 & 讀取
那你是不是就能想到, ArrayList 是數組實現的,所以實現了 RandomAccess 接口, LinkedList 是用鏈表實現的,所以它沒有用 RandomAccess 接口實現吧?
beautiful ~就是這樣
咱瞅瞅 LinkedList 源碼
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
果然,跟咱們設想的一樣,沒有實現 RandomAccess 接口
那為啥 LinkedList 接口使用 for 循環去遍歷的時候,慢的不行呢?
咱們瞅瞅 LinkedList 在 get 元素時,都干了點兒啥
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
Node<E> node(int index) {
// assert isElementIndex(index);
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
在 get 方法中,主要調用了 node() 方法,因為 LinkedList 是雙向鏈表,所以 if (index < (size >> 1)) 在判斷 i 是在前半段還是后半段,如果是前半段就正序遍歷,如果是在后半段那就倒序遍歷,那么為什么使用 for 循環遍歷 LinkedList 時,會這么慢?(好像離真相越來越近了
原因就在兩個 for 循環之中,以第一個 for 循環為例
get(0) :直接拿到了node0 地址,然后拿到 node0 的數據
get(1) :先拿到 node0 地址,然后 i < index ,開始拿 node1 的地址,符合條件,然后去拿 node1 的數據
get(2) :先拿到 node0 的地址,然后 i < index ,拿到 node1 的地址, i < index ,繼續向下走,拿到 node2 的地址,符合條件,獲取 node2 的數據
發現問題了嘛?我就是想要 2 的數據, LinkedList 在遍歷時,將 0 和 1 也給遍歷了,如果數據量非常大的話,那效率可不就唰唰的下來了嘛
那到現在,咱們也就非常明確了,如果是要遍歷 ArrayList 的話,最好是用 for 循環去做,如果要遍歷 LinkedList 的話,最好是用迭代器去做
我猜你一定會說,阿粉啊,那如果對方就給我傳過來了一個 list ,我不知道它是 ArrayList 還是 LinkedList 呀?我該怎么辦呢
還記得 ArrayList 和 LinkedList 有什么不同嗎?是不是 ArrayList 實現了 RandomAccess 接口,但是 LinkedList 沒有實現,所以可以從這點去著手解決
暖暖的阿粉在這里給個簡單的小 demo ,可以參考下:
public class ListTest {
public static void main(String[] args) {
List<String> arrayList = new ArrayList<String>();
arrayList.add("aaa");
arrayList.add("bbb");
isUseIterator(arrayList);
List<String> linkedList = new LinkedList<String>();
linkedList.add("ccc");
linkedList.add("ddd");
isUseIterator(linkedList);
}
public static void isUseIterator(List list){
if (list instanceof RandomAccess){
System.out.println("實現了 RandomAccess 接口,使用 for 循環遍歷");
for (int i = 0 ; i < list.size(); i++ ){
System.out.println(list.get(i));
}
}else{
System.out.println("沒有實現 RandomAccess 接口,使用迭代器遍歷");
Iterator it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
}
}
“LinkedList與ArrayList新增/刪除元素效率哪個更快”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。