欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java數(shù)據(jù)結(jié)構(gòu)之ArrayList從順序表到實現(xiàn)

 更新時間:2023年04月28日 08:30:12   作者:ZIYE_190  
Java中的ArrayList是一種基于數(shù)組實現(xiàn)的數(shù)據(jù)結(jié)構(gòu),支持動態(tài)擴容和隨機訪問元素,可用于實現(xiàn)順序表等數(shù)據(jù)結(jié)構(gòu)。ArrayList在內(nèi)存中連續(xù)存儲元素,支持快速的隨機訪問和遍歷。通過學習ArrayList的實現(xiàn)原理和使用方法,可以更好地掌握Java中的數(shù)據(jù)結(jié)構(gòu)和算法

1 ArrayList

在集合框架中,ArrayList是一個普通的類,實現(xiàn)了List接口,具體框架圖如下:

說明:

  • ArrayList實現(xiàn)了RandomAccess接口,表明ArrayList支持隨機訪問
  • ArrayList實現(xiàn)了Cloneable接口,表明ArrayList是可以clone的
  • ArrayList實現(xiàn)了Serializable接口,表明ArrayList是支持序列化的
  • 和Vector不同,ArrayList不是線程安全的,在單線程下可以使用,在多線程中可以選擇Vector或者CopyOnWriteArrayList
  • ArrayList底層是一段連續(xù)的空間,并且可以動態(tài)擴容,是一個動態(tài)類型的順序表

2 ArrayList使用

2.1 ArrayList的構(gòu)造

方法解釋
ArrayList()無參構(gòu)造
ArrayList(Collection<? extends E> c)利用其他 Collection 構(gòu)建 ArrayList
ArrayList(int initialCapacity)指定順序表初始容量
public static void main(String[] args) {
	// ArrayList創(chuàng)建,推薦寫法
	// 構(gòu)造一個空的列表
	List<Integer> list1 = new ArrayList<>();
	// 構(gòu)造一個具有10個容量的列表
	List<Integer> list2 = new ArrayList<>(10);
	list2.add(1);
	list2.add(2);
	list2.add(3);
	// list2.add("hello"); // 編譯失敗,List<Integer>已經(jīng)限定了,list2中只能存儲整形元素
	// list3構(gòu)造好之后,與list中的元素一致
	ArrayList<Integer> list3 = new ArrayList<>(list2);
	// 避免省略類型,否則:任意類型的元素都可以存放,使用時將是一場災難
	List list4 = new ArrayList();
	list4.add("111");
	list4.add(100);
}

2.2 ArrayList常見操作

方法解釋
boolean add(E e)尾插 e
void add(int index, E element)將 e 插入到 index 位置
boolean addAll(Collection<? extends E> c)尾插 c 中的元素
E remove(int index)刪除 index 位置元素
boolean remove(Object o)刪除遇到的第一個 o
E get(int index)獲取下標 index 位置元素
E set(int index, E element)將下標 index 位置元素設(shè)置為 element
void clear()清空
boolean contains(Object o)判斷 o 是否在線性表中
int indexOf(Object o)返回第一個 o 所在下標
int lastIndexOf(Object o)返回最后一個 o 的下標
List subList(int fromIndex, int toIndex)截取部分 list
public static void main(String[] args) {
	List<String> list = new ArrayList<>();
	list.add("JavaSE");
	list.add("JavaWeb");
	list.add("JavaEE");
	list.add("JVM");
	list.add("測試課程");
	System.out.println(list);
	// 獲取list中有效元素個數(shù)
	System.out.println(list.size());
	// 獲取和設(shè)置index位置上的元素,注意index必須介于[0, size)間
	System.out.println(list.get(1));
	list.set(1, "JavaWEB");
	System.out.println(list.get(1));
	// 在list的index位置插入指定元素,index及后續(xù)的元素統(tǒng)一往后搬移一個位置
	list.add(1, "Java數(shù)據(jù)結(jié)構(gòu)");
	System.out.println(list);
	// 刪除指定元素,找到了就刪除,該元素之后的元素統(tǒng)一往前搬移一個位置
	list.remove("JVM");
	System.out.println(list);
	// 刪除list中index位置上的元素,注意index不要超過list中有效元素個數(shù),否則會拋出下標越界異常
	list.remove(list.size()-1);
	System.out.println(list);

//輸出結(jié)果:
[JavaSE, JavaWeb, JavaEE, JVM, 測試課程]
5
JavaWeb
JavaWEB
[JavaSE, Java數(shù)據(jù)結(jié)構(gòu), JavaWEB, JavaEE, JVM, 測試課程]
[JavaSE, Java數(shù)據(jù)結(jié)構(gòu), JavaWEB, JavaEE, 測試課程]
[JavaSE, Java數(shù)據(jù)結(jié)構(gòu), JavaWEB, JavaEE]

2.3 ArrayList的遍歷

ArrayList 可以使用三方方式遍歷:for循環(huán)+下標、foreach、使用迭代器

public static void main(String[] args) {
	List<Integer> list = new ArrayList<>();
	list.add(1);
	list.add(2);
	list.add(3);
	list.add(4);
	list.add(5);
	// 使用下標+for遍歷
	for (int i = 0; i < list.size(); i++) {
		System.out.print(list.get(i) + " ");
	} 
	System.out.println();
	// 借助foreach遍歷
	for (Integer integer : list) {
		System.out.print(integer + " ");
	} 
	System.out.println();
	Iterator<Integer> it = list.listIterator();
	while(it.hasNext()){
	System.out.print(it.next() + " ");
	} 
	System.out.println();
}

//輸出結(jié)果:
1 2 3 4 5 
1 2 3 4 5 
1 2 3 4 5 

2.4 ArrayList的擴容機制

ArrayList是一個動態(tài)類型的順序表,即:在插入元素的過程中會自動擴容:以下是ArrayList源碼中擴容方式

Object[] elementData; // 存放元素的空間
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 默認空間
private static final int DEFAULT_CAPACITY = 10; // 默認容量大小
public boolean add(E e) {
	ensureCapacityInternal(size + 1); // Increments modCount!!
	elementData[size++] = e;
	return true;
}
private void ensureCapacityInternal(int minCapacity) {
	ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
	if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
		return Math.max(DEFAULT_CAPACITY, minCapacity);
	} 
	return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
	modCount++;
	// overflow-conscious code
	if (minCapacity - elementData.length > 0)
		grow(minCapacity);
	}
	private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
	private void grow(int minCapacity) {
	// 獲取舊空間大小
	int oldCapacity = elementData.length;
	// 預計按照1.5倍方式擴容
	int newCapacity = oldCapacity + (oldCapacity >> 1);
	// 如果用戶需要擴容大小 超過 原空間1.5倍,按照用戶所需大小擴容
	if (newCapacity - minCapacity < 0)
	newCapacity = minCapacity;
	// 如果需要擴容大小超過MAX_ARRAY_SIZE,重新計算容量大小
	if (newCapacity - MAX_ARRAY_SIZE > 0)
	newCapacity = hugeCapacity(minCapacity);
	// 調(diào)用copyOf擴容
	elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
	// 如果minCapacity小于0,拋出OutOfMemoryError異常
	if (minCapacity < 0)
	throw new OutOfMemoryError();
	return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}

檢測是否真正需要擴容,如果是調(diào)用grow準備擴容

預估需要庫容的大小

  • 初步預估按照1.5倍大小擴容
  • 如果用戶所需大小超過預估1.5倍大小,則按照用戶所需大小擴容
  • 真正擴容之前檢測是否能擴容成功,防止太大導致擴容失敗

使用copyOf進行擴容

3 使用示例

撲克牌:

public class Card {
	public int rank; // 牌面值
	public String suit; // 花色
	@Override
	public String toString() {
		return String.format("[%s %d]", suit, rank);
	}
}
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
public class CardDemo {
	public static final String[] SUITS = {"?", "?", "?", "?"};
	// 買一副牌
	private static List<Card> buyDeck() {
		List<Card> deck = new ArrayList<>(52);
		for (int i = 0; i < 4; i++) {
			for (int j = 1; j <= 13; j++) {
				String suit = SUITS[i];
				int rank = j;
				Card card = new Card();
				card.rank = rank;
				card.suit = suit;
				deck.add(card);
			}
		} 
		return deck;
	}
	private static void swap(List<Card> deck, int i, int j) {
		Card t = deck.get(i);
		deck.set(i, deck.get(j));
		deck.set(j, t);
	}
	private static void shuffle(List<Card> deck) {
		Random random = new Random(20190905);
		for (int i = deck.size() - 1; i > 0; i--) {
			int r = random.nextInt(i);
			swap(deck, i, r);
		}
	}
	public static void main(String[] args) {
		List<Card> deck = buyDeck();
		System.out.println("剛買回來的牌:");
		System.out.println(deck);
		shuffle(deck);
		System.out.println("洗過的牌:");
		System.out.println(deck);
		// 三個人,每個人輪流抓 5 張牌
		List<List<Card>> hands = new ArrayList<>();
		hands.add(new ArrayList<>());
		hands.add(new ArrayList<>());
		hands.add(new ArrayList<>());
		for (int i = 0; i < 5; i++) {
			for (int j = 0; j < 3; j++) {
				hands.get(j).add(deck.remove(0));
			}
		}
 		System.out.println("剩余的牌:");
		System.out.println(deck);
		System.out.println("A 手中的牌:");
		System.out.println(hands.get(0));
		System.out.println("B 手中的牌:");
		System.out.println(hands.get(1));
		System.out.println("C 手中的牌:");
		System.out.println(hands.get(2));
	}
}

運行結(jié)果

剛買回來的牌:
[[♠ 1], [♠ 2], [♠ 3], [♠ 4], [♠ 5], [♠ 6], [♠ 7], [♠ 8], [♠ 9], [♠ 10], [♠ 11], [♠ 12], [♠ 13], [♥ 1], [♥ 2], [♥ 3], [♥ 4], [♥ 5], [♥ 6], [♥ 7],
[♥ 8], [♥ 9], [♥ 10], [♥ 11], [♥ 12], [♥ 13], [♣ 1], [♣ 2], [♣ 3], [♣ 4], [♣ 5], [♣ 6], [♣ 7], [♣ 8], [♣ 9], [♣ 10], [♣ 11], [♣ 12], [♣
13], [♦ 1], [♦ 2], [♦ 3], [♦ 4], [♦ 5], [♦ 6], [♦ 7], [♦ 8], [♦ 9], [♦ 10], [♦ 11], [♦ 12], [♦ 13]]
洗過的牌:
[[♥ 11], [♥ 6], [♣ 13], [♣ 10], [♥ 13], [♠ 2], [♦ 1], [♥ 9], [♥ 12], [♦ 5], [♥ 8], [♠ 6], [♠ 3], [♥ 5], [♥ 1], [♦ 6], [♦ 13], [♣ 12], [♦ 12],
[♣ 5], [♠ 4], [♣ 3], [♥ 7], [♦ 3], [♣ 2], [♠ 1], [♦ 2], [♥ 4], [♦ 8], [♠ 10], [♦ 11], [♥ 10], [♦ 7], [♣ 9], [♦ 4], [♣ 8], [♣ 7], [♠ 8], [♦ 9], [♠
12], [♠ 11], [♣ 11], [♦ 10], [♠ 5], [♠ 13], [♠ 9], [♠ 7], [♣ 6], [♣ 4], [♥ 2], [♣ 1], [♥ 3]]
剩余的牌:
[[♦ 6], [♦ 13], [♣ 12], [♦ 12], [♣ 5], [♠ 4], [♣ 3], [♥ 7], [♦ 3], [♣ 2], [♠ 1], [♦ 2], [♥ 4], [♦ 8], [♠ 10], [♦ 11], [♥ 10], [♦ 7], [♣ 9], [♦
4], [♣ 8], [♣ 7], [♠ 8], [♦ 9], [♠ 12], [♠ 11], [♣ 11], [♦ 10], [♠ 5], [♠ 13], [♠ 9], [♠ 7], [♣ 6], [♣ 4], [♥ 2], [♣ 1], [♥ 3]]
A 手中的牌:
[[♥ 11], [♣ 10], [♦ 1], [♦ 5], [♠ 3]]
B 手中的牌:
[[♥ 6], [♥ 13], [♥ 9], [♥ 8], [♥ 5]]
C 手中的牌:
[[♣ 13], [♠ 2], [♥ 12], [♠ 6], [♥ 1]]

到此這篇關(guān)于Java數(shù)據(jù)結(jié)構(gòu)之ArrayList從順序表到實現(xiàn)的文章就介紹到這了,更多相關(guān)Java ArrayList內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java開發(fā)SSM框架具有rest風格的SpringMVC

    java開發(fā)SSM框架具有rest風格的SpringMVC

    這篇文章主要介紹了java開發(fā)中如何使SSM框架具有rest風格的SpringMVC實現(xiàn)解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-10-10
  • Springboot集成swagger實現(xiàn)方式

    Springboot集成swagger實現(xiàn)方式

    這篇文章主要介紹了Springboot集成swagger實現(xiàn)方式,通過簡單的示例代碼詳細描述了實現(xiàn)過程步驟,有需要的朋友可以借鑒參考下,希望可以有所幫助
    2021-08-08
  • jar包手動添加到本地maven倉庫的步驟詳解

    jar包手動添加到本地maven倉庫的步驟詳解

    在寫程序的過程中,有時候會遇到私服里沒有需要的jar包的情況,這時候我們就可以手動導入jar包到本地倉庫進行使用,下面這篇文章主要給大家介紹了關(guān)于jar包手動添加到本地maven倉庫的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • Java page cache回寫機制案例詳解

    Java page cache回寫機制案例詳解

    這篇文章主要介紹了Java page cache回寫機制案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • 聊聊注解@Aspect的AOP實現(xiàn)操作

    聊聊注解@Aspect的AOP實現(xiàn)操作

    這篇文章主要介紹了聊聊注解@Aspect的AOP實現(xiàn)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • Java實現(xiàn)把文件及文件夾壓縮成zip

    Java實現(xiàn)把文件及文件夾壓縮成zip

    這篇文章主要介紹了Java實現(xiàn)把文件及文件夾壓縮成zip,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03
  • Spring @Conditional注解講解及示例詳解

    Spring @Conditional注解講解及示例詳解

    這篇文章主要介紹了Spring @Conditional注解講解及示例詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-12-12
  • SpringBoot如何獲取當前操作用戶的id/信息

    SpringBoot如何獲取當前操作用戶的id/信息

    在一般性的基設(shè)需求中,有需要獲取當前用戶操作記錄的情況,也就是說我們需要記錄當前用戶的信息,如:id、昵稱、賬號等信息,這篇文章主要介紹了SpringBoot獲取當前操作用戶的id/信息,需要的朋友可以參考下
    2023-10-10
  • Java中不用第三個變量來互換兩個變量的值

    Java中不用第三個變量來互換兩個變量的值

    在程序運行期間,隨時可能產(chǎn)生一些臨時數(shù)據(jù),應(yīng)用程序會將這些數(shù)據(jù)保存在一些內(nèi)存單元中,每個內(nèi)存單元都用一個標識符來標識。這些內(nèi)存單元被稱為變量,定義的標識符就是變量名,內(nèi)存單元中存儲的數(shù)據(jù)就是變量的值
    2021-10-10
  • java 驗證碼的生成實現(xiàn)

    java 驗證碼的生成實現(xiàn)

    這篇文章主要介紹了java 驗證碼的生成實現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2017-08-08

最新評論