Java提高篇(三二)-----List總結
前面LZ已經充分介紹了大部分關於List介面的知識,如ArrayList、LinkedList、Vector、Stack,透過這幾個知識點可以對List介面有了比較深的了解了。只有透過歸納總結的知識才是你的知識。所以下面LZ就List介面做一個總結。建議閱讀:
java java提高篇(二二)-----LinkedList
java提高篇(二九)-----Vector
一、List介面概述
List介面,成為有序的Collection也就是序列。此介面可以對清單中的每一個元素的插入位置進行精確的控制,同時使用者可以根據元素的整數索引(在清單中的位置)存取元素,並蒐索清單中的元素。 下圖是List介面的架構圖:
Collection 層級結構中的根介面。它表示一組對象,這些對像也稱為 collection 的元素。對於Collection而言,它不提供任何直接的實現,所有的實現全部都由它的子類別負責。
AbstractCollection:
提供 Collection 介面的骨幹實現,以最大限度地減少了實現此介面所需的工作。對於我們而言要實作一個不可修改的 collection,只需擴展此類,並提供 iterator 和 size 方法的實作。但要實作可修改的 collection,就必須另外重寫此類別的 add 方法(否則,會拋出 UnsupportedOperationException),iterator 方法傳回的迭代器還必須另外實作其 remove 方法。terator:
迭代器。ListIterator:
系列表迭代器,允許程式設計師按任何方向遍歷列表、迭代期間修改列表,並在列表中的當前位置。List:
繼承於Collection的介面。它代表有序的隊列。AbstractList:
List 介面的骨幹實現,以最大限度地減少實現「隨機存取」資料儲存(如數位List 介面的骨幹實現,以最大限度地減少實現「隨機存取」資料儲存(如數組)支援的該介面所需的工作。 Queue:
隊列。提供隊列基本的插入、取得、檢查操作。 Deque:一個線性 collection,支援在兩端插入和移除元素。大多數 Deque 實作對於它們能夠包含的元素數沒有固定限制,但此介面既支援有容量限制的雙端佇列,也支援沒有固定大小限制的雙端佇列。 AbstractSequentialList:從某種意義上說,此類與在列表的列表迭代器上實現“隨機訪問”方法。 LinkedList:List 介面的連結清單實作。它實作所有可選的列表操作。 ArrayList:List 介面的大小可變數組的實作。它實現了所有可選列表操作,並允許包括 null 在內的所有元素。除了實作 List 介面外,此類還提供一些方法來操作內部用來儲存清單的陣列的大小。 Vector:實現可成長的物件陣列。與陣列一樣,它包含可以使用整數索引進行存取的元件。 Stack:後進先出(LIFO)的物件堆疊。它透過五個操作對類別 Vector 進行了擴展 ,允許將向量視為堆疊。 Enumeration:枚舉,實現了該介面的對象,它產生一系列元素,一次產生一個。連續呼叫 nextElement 方法將傳回一系列的連續元素。 每個知識點都有它的使用範圍。集合也是如此,在Java中集合的家族非常龐大,每個成員都有最適合的使用場景。在剛接觸List時,LZ就說過如果涉及「堆疊」、「佇列」、「鍊錶」等操作,請優先考慮用List。 2.1ArrayList、LinkedList效能分析 在List中我們使用最普遍的是LinkedList和ArrayList,同時我們也了解了他們兩者之間的差異和場景。 二、使用場景
2.1ArrayList、LinkedList效能分析public class ListTest {
private static final int COUNT = 100000;
private static ArrayList arrayList = new ArrayList<>();
private static LinkedList linkedList = new LinkedList<>();
private static Vector vector = new Vector<>();
public static void insertToList(List list){
long startTime = System.currentTimeMillis();
for(int i = 0 ; i < COUNT ; i++){
list.add(0,i);
}
long endTime = System.currentTimeMillis();
System.out.println("插入 " + COUNT + "元素" + getName(list) + "花费 " + (endTime - startTime) + " 毫秒");
}
public static void deleteFromList(List list){
long startTime = System.currentTimeMillis();
for(int i = 0 ; i < COUNT ; i++){
list.remove(0);
}
long endTime = System.currentTimeMillis();
System.out.println("删除" + COUNT + "元素" + getName(list) + "花费 " + (endTime - startTime) + " 毫秒");
}
public static void readList(List list){
long startTime = System.currentTimeMillis();
for(int i = 0 ; i < COUNT ; i++){
list.get(i);
}
long endTime = System.currentTimeMillis();
System.out.println("读取" + COUNT + "元素" + getName(list) + "花费 " + (endTime - startTime) + " 毫秒");
}
private static String getName(List list) {
String name = "";
if(list instanceof ArrayList){
name = "ArrayList";
}
else if(list instanceof LinkedList){
name = "LinkedList";
}
else if(list instanceof Vector){
name = "Vector";
}
return name;
}
public static void main(String[] args) {
insertToList(arrayList);
insertToList(linkedList);
insertToList(vector);
System.out.println("--------------------------------------");
readList(arrayList);
readList(linkedList);
readList(vector);
System.out.println("--------------------------------------");
deleteFromList(arrayList);
deleteFromList(linkedList);
deleteFromList(vector);
}
}
運作結果:
🎜🎜🎜插入 100000元素ArrayList花费 3900 毫秒 插入 100000元素LinkedList花费 15 毫秒 插入 100000元素Vector花费 3933 毫秒 -------------------------------------- 读取100000元素ArrayList花费 0 毫秒 读取100000元素LinkedList花费 8877 毫秒 读取100000元素Vector花费 16 毫秒 -------------------------------------- 删除100000元素ArrayList花费 4618 毫秒 删除100000元素LinkedList花费 16 毫秒 删除100000元素Vector花费 4759 毫秒
从上面的运行结果我们可以清晰的看出ArrayList、LinkedList、Vector增加、删除、遍历的效率问题。下面我就插入方法add(int index, E element),delete、get方法各位如有兴趣可以研究研究。
首先我们先看三者之间的源码:
ArrayList
public void add(int index, E element) { rangeCheckForAdd(index); //检查是否index是否合法 ensureCapacityInternal(size + 1); //扩容操作 System.arraycopy(elementData, index, elementData, index + 1, size - index); //数组拷贝 elementData[index] = element; //插入 size++; }
rangeCheckForAdd、ensureCapacityInternal两个方法没有什么影响,真正产生影响的是System.arraycopy方法,该方法是个JNI函数,是在JVM中实现的。声明如下:
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
目前LZ无法看到源码,具体的实现不是很清楚,不过System.arraycopy源码分析对其进行了比较清晰的分析。但事实上我们只需要了解该方法会移动index后面的所有元素即可,这就意味着ArrayList的add(int index, E element)方法会引起index位置之后所有元素的改变,这真是牵一处而动全身。
LinkedList
public void add(int index, E element) { checkPositionIndex(index); if (index == size) //插入位置在末尾 linkLast(element); else linkBefore(element, node(index)); }
该方法比较简单,插入位置在末尾则调用linkLast方法,否则调用linkBefore方法,其实linkLast、linkBefore都是非常简单的实现,就是在index位置插入元素,至于index具体为知则有node方法来解决,同时node对index位置检索还有一个加速作用,如下:
Node<E> node(int index) { if (index < (size >> 1)) { //如果index 小于 size/2 则从头开始查找 Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; return x; } else { //如果index 大于 size/2 则从尾部开始查找 Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }
所以linkedList的插入动作比ArrayList动作快就在于两个方面。1:linkedList不需要执行元素拷贝动作,没有牵一发而动全身的大动作。2:查找插入位置有加速动作即:若index < 双向链表长度的1/2,则从前向后查找; 否则,从后向前查找。
Vector
Vector的实现机制和ArrayList一样,同样是使用动态数组来实现的,所以他们两者之间的效率差不多,add的源码也一样,如下:
public void add(int index, E element) { insertElementAt(element, index); } public synchronized void insertElementAt(E obj, int index) { modCount++; if (index > elementCount) { throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount); } ensureCapacityHelper(elementCount + 1); System.arraycopy(elementData, index, elementData, index + 1, elementCount - index); elementData[index] = obj; elementCount++; }
上面是针对ArrayList、LinkedList、Vector三者之间的add(int index,E element)方法的解释,解释了LinkedList的插入动作要比ArrayList、Vector的插入动作效率为什么要高出这么多!至于delete、get两个方法LZ就不多解释了。
同时LZ在写上面那个例子时发现了一个非常有趣的现象,就是linkedList在某些时候执行add方法时比ArrayList方法会更慢!至于在什么情况?为什么会慢LZ下篇博客解释,当然不知道这个情况各位是否也遇到过??
2.2、Vector和ArrayList的区别
四、更多
java提高篇(二一)-----ArrayList
java提高篇(二二)-----LinkedList
java提高篇(二九)-----Vector
Java提高篇(三一)-----Stack
以上是JavaList PHP中文網(www.php.cn)!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

膠囊是一種三維幾何圖形,由一個圓柱體和兩端各一個半球體組成。膠囊的體積可以通過將圓柱體的體積和兩端半球體的體積相加來計算。本教程將討論如何使用不同的方法在Java中計算給定膠囊的體積。 膠囊體積公式 膠囊體積的公式如下: 膠囊體積 = 圓柱體體積 兩個半球體體積 其中, r: 半球體的半徑。 h: 圓柱體的高度(不包括半球體)。 例子 1 輸入 半徑 = 5 單位 高度 = 10 單位 輸出 體積 = 1570.8 立方單位 解釋 使用公式計算體積: 體積 = π × r2 × h (4

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。

PHP和Python各有優勢,適合不同場景。 1.PHP適用於web開發,提供內置web服務器和豐富函數庫。 2.Python適合數據科學和機器學習,語法簡潔且有強大標準庫。選擇時應根據項目需求決定。

Java是熱門程式語言,適合初學者和經驗豐富的開發者學習。本教學從基礎概念出發,逐步深入解說進階主題。安裝Java開發工具包後,可透過建立簡單的「Hello,World!」程式來實踐程式設計。理解程式碼後,使用命令提示字元編譯並執行程序,控制台上將輸出「Hello,World!」。學習Java開啟了程式設計之旅,隨著掌握程度加深,可創建更複雜的應用程式。

Spring Boot簡化了可靠,可擴展和生產就緒的Java應用的創建,從而徹底改變了Java開發。 它的“慣例慣例”方法(春季生態系統固有的慣例),最小化手動設置
