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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

程序员应该吃透的集合List

發(fā)布時間:2023/11/28 生活经验 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 程序员应该吃透的集合List 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一:先看看集合框架接口圖

? ? ? ??(圖片來源于網(wǎng)絡)

?

? ? ?? 從圖中可以看到List實現(xiàn)了Collection接口。

二:Collection接口是什么?

? ? ? 在java類庫中,Collection接口是集合類的基本接口,這個接口有兩個基本的方法:

? ? ??

public interface Collection<E> extends Iterable<E>
{boolean add(E element);Iterator<E> iterator();...
}

?

? add方法用于向集合中添加元素。如果添加元素確實改變了集合就返回true,如果集合沒有發(fā)生改變就返回false。列如,向一個 ? 集合中添加一個已經(jīng)存在的對象,這個添加請求就沒有效果會返回false,因為Set集合不允許重復對象。從代碼中可以看到, ? ? ? Collection接口還包括了一個iterator()方法,返回類型為Iterator接口對象,那么什么Iterator接口?

? Collection接口中的其它方法:

??

//添加方法:
add(Object o) //添加指定元素
addAll(Collection c) //添加指定集合
//刪除方法:
remove(Object o) //刪除指定元素
removeAll(Collection c) //輸出兩個集合的交集
retainAll(Collection c) //保留兩個集合的交集
clear() //清空集合
//查詢方法:
size() //集合中的有效元素個數(shù)
toArray() //將集合中的元素轉換成Object類型數(shù)組
//判斷方法:
isEmpty() //判斷是否為空
equals(Object o) //判斷是否與指定元素相同
contains(Object o) //判斷是否包含指定元素
containsAll(Collection c) //判斷是否包含指定集合

? List接口中的方法

//添加方法:
add(int index, Object o) //向指定位置添加元素
addAll(int index, Collection c) //向指定位置添加集合
//刪除方法
remove(int index) //刪除指定元素
//查詢方法:
get(int index) //獲取指定位置的元素
indexOf(Object o) //獲取指定元素的位置
lastIndexOf(Object o) //獲取指定元素最后一次出現(xiàn)的位置
//修改方法:
subList(int fromIndex, int toIndex) //截取子集合從fromIndex到toIndex,要頭不要尾
set(int index, Object o) //修改指定位置的元素

三:迭代器

? ? 翻看Iterator接口源碼

? ??

public interface Iterator<E> {boolean hasNext();E next();default void remove() {throw new UnsupportedOperationException("remove");}default void forEachRemaining(Consumer<? super E> action) {Objects.requireNonNull(action);while (hasNext())action.accept(next());}
}

? 很明顯的可以看到,這個Iterator接口就像當于鏈表中的結點,只不過在C語言里結點里的指針在java中變成了對象的引用。那么 我們就應該知道,通過反復的調(diào)用nest()就可以逐個的訪問集合中的每個元素,但是當?shù)竭_了集合的末尾,nest方法將拋出一個NoSuchElementException。因此,每次都用next方法前都應該調(diào)用hasNext方法進行判斷。hasNext方法的作用是判斷對象是否還有下一個元素,有就返回true,否則返回false。remove方法會刪除上次調(diào)用next方法時返回的元素。就像是刪除一個元素之前先看下它是很有必要的,remove方法就是按照這個理念設計的。舉一個訪問集合中所有元素的案例:

	Collection<String> s = new ArrayList<String>();s.add("xiaohong");s.add("xionming");s.add("wanger");Iterator<String> iterator = s.iterator();while(iterator.hasNext()) {String element = iterator.next();System.out.println(element);}

在Java SE8版本中,新加入了for each循環(huán)遍歷,編譯器簡單地將“for each”循環(huán)翻譯為帶有迭代器的循環(huán)。

for (String string : s){System.out.println(string);}

顯然,通過"for each"遍歷使得代碼更加簡潔,所有實現(xiàn)了Iterable接口的對象都可以使用"for each"循環(huán)。Collection接口擴展了Iterable接口。

?

四:具體的實現(xiàn)類

1.AbstractList

? 如果實現(xiàn)了Collection接口的每一個類都要實現(xiàn)它的所有方法,那么將是一件很煩的事情。此時,AbstractList應運而生。

它將基礎的iterator抽象化,其它的方法給實現(xiàn)了,此時一個具體的集合類就可以擴展AbstractList類,并且只需提供Iterator方法,當然如果不滿意AbstractList類實現(xiàn)的方法也可以在子類重寫它的方法。

?2.ArrayList

ArrayList 的底層是數(shù)組隊列,相當于動態(tài)數(shù)組。與 Java 中的數(shù)組相比,它的容量能動態(tài)增長。在添加大量元素前,應用程序可以使用ensureCapacity操作來增加 ArrayList 實例的容量。這可以減少遞增式再分配的數(shù)量。

它繼承于 AbstractList,實現(xiàn)了 List, RandomAccess, Cloneable, java.io.Serializable 這些接口。

在我們學數(shù)據(jù)結構的時候就知道了線性表的順序存儲,插入刪除元素的時間復雜度為O(n),求表長以及增加元素,取第 i 元素的時間復雜度為O(1)

  • ArrayList 繼承了AbstractList,實現(xiàn)了List。它是一個數(shù)組隊列,提供了相關的添加、刪除、修改、遍歷等功能。
  • ArrayList 實現(xiàn)了RandomAccess 接口, RandomAccess 是一個標志接口,表明實現(xiàn)這個這個接口的 List 集合是支持快速隨機訪問的。在 ArrayList 中,我們即可以通過元素的序號快速獲取元素對象,這就是快速隨機訪問。
  • ArrayList 實現(xiàn)了Cloneable 接口,即覆蓋了函數(shù) clone(),能被克隆。
  • ArrayList 實現(xiàn)java.io.Serializable 接口,這意味著ArrayList支持序列化,能通過序列化去傳輸。

  和 Vector 不同,ArrayList 中的操作不是線程安全的!所以,建議在單線程中才使用 ArrayList,而在多線程中可以選擇 Vector 或者 CopyOnWriteArrayList。

ArrayList中特有的方法

ensureCapacity(int minCapactiy) //判斷當前數(shù)組中的元素個數(shù)是否大于指定的minCapacity
trimToSize() //修改數(shù)組容量為當前數(shù)組有效元素個數(shù)

3.LinkedList

? ?? LinkedList是一個實現(xiàn)了List接口和Deque接口的雙端鏈表。 LinkedList底層的鏈表結構使它支持高效的插入和刪除操作,另外它實現(xiàn)了Deque接口,使得LinkedList類也具有隊列的特性; LinkedList不是線程安全的,如果想使LinkedList變成線程安全的,可以調(diào)用靜態(tài)類Collections類中的synchronizedList方法.。

需要提一下的是,LinkedList類中有一個ListIterator<E> listIterator方法,listIterator接口中包含一個add方法:

public interface ListIterator<E> extends Iterator<E> {boolean hasNext();E next();boolean hasPrevious();void set(E e);void add(E e);
}

?

因為鏈表是一個有序的集合,每個對象的位置就顯得十分重要。LinkedList中的add方法只能將對象添加到鏈表尾部,而經(jīng)常卻要將對象添加到鏈表的中間,迭代器就是用于描述集合中的位置的,所以這種依賴位置的方法就交由迭代器來完成。因為Set集合是無序的,所以在Iterator接口中就沒有add方法,而是擴展了一個LinkIterator接口來實現(xiàn)。

值得一提的是:大家都知道,鏈表是不支持快速隨機訪問的。如果要查看鏈表中的第n個元素,就必須從頭開始,越過n-1個元素,沒有捷徑可走,但盡管如此,LinkedList還是提供了一個用來訪問某個特定元素的get方法,當然這個方法的效率并不高,如果在使用這個方法,那么可能對于所要解決的問題使用了錯誤的數(shù)據(jù)結構。LinkedList類中get方法所謂的隨機訪問都是需要從列表的頭部開始搜索,效率極低。使用鏈表的唯一理由是盡可能的減少在鏈表中間插入或刪除元素所付出的代價。

LinkedList中特有的方法

//查詢方法:
getFirst() //獲取集合中的第一個元素
getLast() //獲取集合中的最后一個元素
//添加方法:
addFirst(Object o) //在集合的第一個位置添加指定元素
addLast(Object o) //在集合的最后一個位置添加指定元素
//刪除方法:
removeFirst() //刪除集合中的第一個元素
removeLast() //刪除集合中的最后一個元素

?下面程序簡單的創(chuàng)建了兩個鏈表,將它們合并在一起,然后從第二個鏈表中每隔一個元素刪除一個元素,最后測試removeAll()方 法 :?

package listdemo;import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;public class LinkedListTest {public static void main(String[] args) {List<String> a = new LinkedList<>();a.add("aaa");a.add("bbb");a.add("eee");List<String> b = new LinkedList<>();b.add("AAA");b.add("BBB");b.add("EEE");ListIterator<String> aIter = a.listIterator();ListIterator<String> bIter = b.listIterator();//a集合合并b集合while(bIter.hasNext()) {if(aIter.hasNext())aIter.next();aIter.add(bIter.next());}System.out.println(a);//從b鏈表中每間隔一個元素刪除一個元素while(bIter.hasNext()) {bIter.next();//跳過一個元素if(bIter.hasNext()) {bIter.next();bIter.remove();//先查后刪}}System.out.println(b);//測試刪除所有a.removeAll(a);System.out.println(a);}
}

五:最后來看看ArrayList與LinkedList的區(qū)別

  • 1. 是否保證線程安全: ArrayListLinkedList 都是不同步的,也就是不保證線程安全;

  • 2. 底層數(shù)據(jù)結構: Arraylist 底層使用的是 Object 數(shù)組LinkedList 底層使用的是 雙向鏈表 數(shù)據(jù)結構(JDK1.6之前為循環(huán)鏈表,JDK1.7取消了循環(huán)。注意雙向鏈表和雙向循環(huán)鏈表的區(qū)別,下面有介紹到!)

  • 3. 插入和刪除是否受元素位置的影響:ArrayList 采用數(shù)組存儲,所以插入和刪除元素的時間復雜度受元素位置的影響。 比如:執(zhí)行add(E e) 方法的時候, ArrayList 會默認在將指定的元素追加到此列表的末尾,這種情況時間復雜度就是O(1)。但是如果要在指定位置 i 插入和刪除元素的話(add(int index, E element) )時間復雜度就為 O(n-i)。因為在進行上述操作的時候集合中第 i 和第 i 個元素之后的(n-i)個元素都要執(zhí)行向后位/向前移一位的操作。 ② LinkedList 采用鏈表存儲,所以插入,刪除元素時間復雜度不受元素位置的影響,都是近似 O(1)而數(shù)組為近似 O(n)。

  • 4. 是否支持快速隨機訪問: LinkedList 不支持高效的隨機元素訪問,而 ArrayList 支持。快速隨機訪問就是通過元素的序號快速獲取元素對象(對應于get(int index) 方法)。

  • ? ? ? ? 5. 內(nèi)存空間占用: ArrayList的空 間浪費主要體現(xiàn)在在list列表的結尾會預留一定的容量空間,而LinkedList的空間花費則體 ? 現(xiàn)在它的每一個元素都需要消耗比ArrayList更多的空間(因為要存放直接后繼和直接前驅以及數(shù)據(jù))。

?

推薦閱讀:

  • 集合詳解之Set
  • Java集合詳解之Map
  • Java集合之并發(fā)容器

參考引用:

  1. ?java核心思想
  2. Java集合框架常見面試題
  3. Java中的Collection集合接口常用方法

?

總結

以上是生活随笔為你收集整理的程序员应该吃透的集合List的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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