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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

list容器java_【Java容器】List容器使用方法及源码分析

發(fā)布時間:2023/12/15 java 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 list容器java_【Java容器】List容器使用方法及源码分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

List容器

ArrayList:使用動態(tài)數(shù)組保存元素,支持隨機訪問。

Vector:與ArrayList類似,但是它是線程安全的。

LinkedList:使用雙向鏈表保存元素,只能順序訪問,此外可以用作為棧、隊列和雙向隊列。

1 ArrayList

1.1 簡介

基于動態(tài)數(shù)組實現(xiàn)了List接口。除了List接口的所有方法之外,還提供了調(diào)整內(nèi)部數(shù)組大小的方法。該類與Vector類大致相同,區(qū)別在于ArrayList是不支持同步的。

size,isEmpty,get,set,iterator和listIterator方法都只需時間復(fù)雜度為O(1)。其他的操作時間復(fù)雜度為O(n)。且常數(shù)因子與LinkedList類相比更低。

每個ArrayList實例都有一個capacity,描述了該列表中實際用于存儲元素的數(shù)組的大小。當向列表中添加元素時,capacity會自動增大。使用ensureCapacity方法,可以在向列表中添加大量元素之前先使數(shù)組擴容,避免列表自身多次自動擴容。

1.2 存儲結(jié)構(gòu)

ArrayList內(nèi)部使用一個數(shù)組來保存元素,ArrayList的容量就表示該數(shù)組的大小,

transient Object[] elementData; // non-private to simplify nested class access

任何空的ArrayList中的elementData數(shù)組用一個默認的空數(shù)組表示,

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

當向空ArrayList中添加第一個元素時,會擴容到DEFAULT_CAPACITY大小,

private static final int DEFAULT_CAPACITY = 10;

此外,ArrayList中還使用一個size記錄當前保存元素的個數(shù),

private int size;

1.3 添加元素

add(E e)方法可以向ArrayList的末尾添加一個元素,

public boolean add(E e) {

ensureCapacityInternal(size + 1); // Increments modCount!!

elementData[size++] = e;

return true;

}

其中會先調(diào)用ensureCapacityInternal(int minCapacity)方法對elementData數(shù)組的大小進行檢查與擴容,

private void ensureCapacityInternal(int minCapacity) {

// ensureCapacity(int minCapacity)方法返回數(shù)組所需要的大小

ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));

}

然后調(diào)用ensureExplicitCapacity(int minCapacity)方法,

private void ensureExplicitCapacity(int minCapacity) {

modCount++;

// overflow-conscious code

if (minCapacity - elementData.length > 0)

grow(minCapacity);

}

使用grow(int minCapacity)方法對數(shù)組進行擴容并復(fù)制舊數(shù)組的元素到新數(shù)組中,

private void grow(int minCapacity) {

// overflow-conscious code

int oldCapacity = elementData.length;

// 先設(shè)置新容量為舊容量的1.5倍

int newCapacity = oldCapacity + (oldCapacity >> 1);

// 如果新容量小于傳入的要求容量,則新容量以要求容量為準

if (newCapacity - minCapacity < 0)

newCapacity = minCapacity;

// 如果新容量大于MAX_ARRAY_SIZE(2^31-1-8)

if (newCapacity - MAX_ARRAY_SIZE > 0)

// 判斷要求容量的大小是否大于MAX_ARRAY_SIZE(2^31-1-8)

// 若要求容量大于MAX_ARRAY_SIZE(2^31-1-8),則新容量為Integer.MAX_VALUE(2^31-1)

// 否則新容量為MAX_ARRAY_SIZE(2^31-1-8)

newCapacity = hugeCapacity(minCapacity);

// minCapacity is usually close to size, so this is a win:

// 將舊數(shù)組元素復(fù)制到新數(shù)組中

elementData = Arrays.copyOf(elementData, newCapacity);

}

1.4 獲取元素

get(int index)方法返回列表中指定位置的元素,

public E get(int index) {

// 檢查下標是否合法

rangeCheck(index);

// 返回元素

return elementData(index);

}

1.5 刪除元素

remove(int index)方法刪除列表中指定位置的元素并將其返回,

public E remove(int index) {

// 檢查下標是否合法

rangeCheck(index);

modCount++;

E oldValue = elementData(index);

// 需要左移的元素個數(shù)

int numMoved = size - index - 1;

if (numMoved > 0)

// 將被刪除元素右邊所有的元素左移一位

System.arraycopy(elementData, index+1, elementData, index,

numMoved);

// 將數(shù)組最后一位設(shè)為null

elementData[--size] = null; // clear to let GC do its work

return oldValue;

}

1.6 fast-fail機制

fail-fast 機制是java集合(Collection)中的一種錯誤機制。作用是在集合的迭代器的迭代期間,如果發(fā)現(xiàn)集合被其他線程修改,則拋出異常,避免執(zhí)行一些不確定的操作。

例如:當某一個線程A通過迭代器去遍歷某集合的過程中,若該集合的內(nèi)容被其他線程所改變了,那么線程A訪問集合時,就會拋出ConcurrentModificationException異常,產(chǎn)生fail-fast事件。

實現(xiàn)方式:

AbstractList中有一個modCount字段用于記錄容器結(jié)構(gòu)發(fā)生變化的次數(shù),

protected transient int modCount = 0;

結(jié)構(gòu)變化指添加或者刪除至少一個元素的所有操作,或者是調(diào)整內(nèi)部數(shù)組的大小,若僅僅設(shè)置元素的值不算作結(jié)構(gòu)發(fā)生變化,例如,

public boolean add(E e) {

ensureCapacityInternal(size + 1); // 增加modCount

elementData[size++] = e;

return true;

}

public E remove(int index) {

rangeCheck(index);

modCount++; // 增加modCount

E oldValue = elementData(index);

int numMoved = size - index - 1;

if (numMoved > 0)

System.arraycopy(elementData, index+1, elementData, index,

numMoved);

elementData[--size] = null; // clear to let GC do its work

return oldValue;

}

在使用ArrayList的迭代器時,迭代器中會記錄當前列表的modCount,

private class Itr implements Iterator {

int cursor; // index of next element to return

int lastRet = -1; // index of last element returned; -1 if no such

int expectedModCount = modCount; // 記錄創(chuàng)建迭代器時,容器的modCount

...

}

在使用迭代器的next(),remove(),previous(),set()或add()方法時,會通過檢測該字段,判斷容器是否被意外地修改了,

// 迭代器類中定義的檢查modCount的方法,在迭代時容器被意外修改時拋出異常

final void checkForComodification() {

if (modCount != expectedModCount)

throw new ConcurrentModificationException();

}

如果容器的modCount與迭代器中記錄的expectedModCount不一致,即容器在迭代器遍歷期間被修改,就會返回ConcurrentModificationException異常。

1.7 同步

使用Collections.synchronizedList方法可以獲得一個線程安全的List,

List list = Collections.synchronizedList(new ArrayList(...)); // 獲取線程安全的List

該方法根據(jù)輸入容器的具體類型,實例化一個SynchronizedCollection類的子類對象,

static class SynchronizedCollection implements Collection, Serializable {

private static final long serialVersionUID = 3053995032091335093L;

final Collection c; // 底層Collection容器

final Object mutex; // 用于加鎖的對象

//構(gòu)造方法

SynchronizedCollection(Collection c) {

this.c = Objects.requireNonNull(c); // 輸入的Collection對象

mutex = this; // 自己作為鎖

}

...

}

在該類中,將原來非線程安全的容器與一個鎖組合,并對幾乎所有方法加synchronized關(guān)鍵詞,使得對容器的操作是線程安全的。

需要注意,當使用SynchronizedCollection類的迭代器時,需要用戶自己手動加鎖,因為iterator()沒有使用同步鎖,

static class SynchronizedCollection implements Collection, Serializable {

...

// 沒有加synchronized修飾

public Iterator iterator() {

return c.iterator(); // Must be manually synched by user!

}

...

}

2 Vector

2.1 簡介

Vector的實現(xiàn)與ArrayList相似,也是通過動態(tài)變化的數(shù)組存儲元素,不過使用了synchronized進行同步,

// 添加元素

public synchronized boolean add(E e) {

modCount++;

ensureCapacityHelper(elementCount + 1);

elementData[elementCount++] = e;

return true;

}

// 獲取元素

public synchronized E get(int index) {

if (index >= elementCount)

throw new ArrayIndexOutOfBoundsException(index);

return elementData(index);

}

// 刪除元素

public synchronized E remove(int index) {

modCount++;

if (index >= elementCount)

throw new ArrayIndexOutOfBoundsException(index);

E oldValue = elementData(index);

int numMoved = elementCount - index - 1;

if (numMoved > 0)

System.arraycopy(elementData, index+1, elementData, index,

numMoved);

elementData[--elementCount] = null; // Let gc do its work

return oldValue;

}

2.2 ArrayList與Vector

Vector是同步的,所以開銷比ArrayList大,性能較低。

Vector每次擴容默認請求的大小是原容量的2倍(可通過capacityIncrement設(shè)置),ArrayList則是原容量1.5倍。

3 LinkedList

3.1 存儲結(jié)構(gòu)

LinkedList使用雙向鏈表保存元素,因此在插入刪除操作的時候相比底層為數(shù)組的ArrayList更快,

// 節(jié)點的結(jié)構(gòu)

private static class Node {

E item;

Node next;

Node prev;

Node(Node prev, E element, Node next) {

this.item = element;

this.next = next;

this.prev = prev;

}

}

// 頭節(jié)點

transient Node first;

// 尾節(jié)點

transient Node last;

3.2 LinkedList與ArrayList

ArrayList基于動態(tài)數(shù)組,LinkedList基于雙向鏈表。

ArrayList支持隨機訪問,LinkedList不支持。

LinkedList在任意位置添加刪除元素更快。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的list容器java_【Java容器】List容器使用方法及源码分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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