亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java數(shù)據(jù)結(jié)構(gòu)之ArrayList與順序表詳解

 更新時間:2025年05月01日 10:55:54   作者:學(xué)無止盡5  
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)之ArrayList與順序表,在Java中,ArrayList是一個可動態(tài)調(diào)整大小的數(shù)組實現(xiàn),它屬于java.util包,ArrayList提供了一種方便的、基于索引的方式來存儲和訪問對象,需要的朋友可以參考下

前言

在 Java編程的廣袤世界里,數(shù)據(jù)結(jié)構(gòu)猶如精巧的建筑藍圖,決定著程序在數(shù)據(jù)處理與存儲時的效率、靈活性以及可擴展性。其中,ArrayList和順序表作為線性數(shù)據(jù)結(jié)構(gòu)的典型代表,猶如兩顆璀璨的明星,在眾多數(shù)據(jù)處理場景中熠熠生輝。

順序表,以其簡潔而直觀的連續(xù)內(nèi)存存儲方式,為數(shù)據(jù)的快速隨機訪問提供了可能。它猶如一位嚴(yán)謹?shù)墓芗?,將?shù)據(jù)元素有條不紊地排列在連續(xù)的內(nèi)存空間中,使得我們能夠通過精確的索引迅速定位到所需的數(shù)據(jù),就像在一本精心編排索引的書籍中快速找到特定章節(jié)一樣高效。這種特性在一些對數(shù)據(jù)訪問速度有嚴(yán)格要求且數(shù)據(jù)量相對固定或可預(yù)知的場景中,展現(xiàn)出了無與倫比的優(yōu)勢。 而 ArrayList,則是 Java 集合框架中備受矚目的一員。它基于數(shù)組實現(xiàn),卻又巧妙地融入了動態(tài)擴容機制,如同一位富有彈性的藝術(shù)家,能夠根據(jù)創(chuàng)作需求靈活調(diào)整畫布的大小。這種動態(tài)性使得 ArrayList在應(yīng)對數(shù)據(jù)量不確定、頻繁增刪元素的復(fù)雜情況時游刃有余。它為開發(fā)者提供了豐富便捷的方法庫,極大地簡化了數(shù)據(jù)操作的流程,仿佛一把瑞士軍刀,在各種數(shù)據(jù)處理任務(wù)中都能發(fā)揮出色的作用。 在實際的編程旅程中,深入理解 ArrayList 和順序表的特性、性能表現(xiàn)以及適用場景,就如同掌握了兩門精湛的技藝。無論是構(gòu)建高效的數(shù)據(jù)庫管理系統(tǒng)、開發(fā)復(fù)雜的算法,還是打造用戶友好的圖形界面應(yīng)用,都離不開對這兩種數(shù)據(jù)結(jié)構(gòu)的精準(zhǔn)運用。本博客將深入剖析 Java ArrayList 和順序表,從原理到實現(xiàn),從性能對比到應(yīng)用場景分析,為你揭開它們神秘的面紗,引領(lǐng)你在 Java編程的數(shù)據(jù)結(jié)構(gòu)之路上穩(wěn)步前行,幫助你在面對各種數(shù)據(jù)處理挑戰(zhàn)時做出明智而高效的抉擇。

一、線性表

線性表(linear list)是n個具有相同特性的數(shù)據(jù)元素的有限序列。 線性表是一種在實際中廣泛使用的數(shù)據(jù)結(jié)構(gòu),常見的線性表:順序表、鏈表、棧、隊列…

線性表在邏輯上是線性結(jié)構(gòu),也就說是連續(xù)的一條直線。但是在物理結(jié)構(gòu)上并不一定是連續(xù)的,線性表在物理上存儲時,通常以數(shù)組和鏈?zhǔn)浇Y(jié)構(gòu)的形式存儲。

在 Java 編程領(lǐng)域,線性表是一種極為基礎(chǔ)且關(guān)鍵的數(shù)據(jù)結(jié)構(gòu),它猶如大廈的基石,支撐起眾多復(fù)雜算法與程序功能的實現(xiàn)。線性表,從直觀上理解,是由一系列具有相同類型的數(shù)據(jù)元素按照特定的順序依次排列而成的集合,其元素之間存在著一對一的線性關(guān)系。

1.1線性表的基本特性

(一)有限性

線性表中的元素數(shù)量是有限的。無論是空表(不包含任何元素),還是包含大量元素的表,其元素個數(shù)總能確定。例如,一個班級的學(xué)生名單,無論班級規(guī)模大小,學(xué)生人數(shù)總歸是可以明確統(tǒng)計的。

(二)有序性

元素在表中的排列具有確定的順序。每個元素都有其特定的位置,除了第一個元素?zé)o前驅(qū),最后一個元素?zé)o后繼外,其他元素都有且僅有一個直接前驅(qū)和一個直接后繼。就像電影院里的座位號,每個座位都有其固定的前后順序。

(三)同一性

表中的所有元素都屬于同一數(shù)據(jù)類型。這一特性使得對線性表的操作能夠具有一致性和規(guī)范性。例如,一個存儲整數(shù)的線性表,其中所有元素都為整型,這樣在進行數(shù)學(xué)運算或數(shù)據(jù)比較等操作時就可以按照統(tǒng)一的整型規(guī)則進行。

1.2線性表在Java中的常見實現(xiàn)方式

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

順序表利用數(shù)組來存儲線性表中的元素。在 Java 中,可以聲明一個數(shù)組來容納這些元素,例如 Object[] data(或指定具體類型如 int[] data 等)。數(shù)組在內(nèi)存中是連續(xù)分配空間的,這使得順序表在隨機訪問元素時具有極高的效率。通過元素的索引,可以直接計算出其在內(nèi)存中的存儲地址,從而快速獲取到該元素,時間復(fù)雜度為 O(1)。

操作實現(xiàn)

插入操作:當(dāng)向順序表中插入一個元素時,如果插入位置不是在表尾,需要將插入位置之后的所有元素依次向后移動一位,為新元素騰出空間,然后再將新元素放入指定位置。這種移動操作在元素數(shù)量較多時可能會耗費較多時間,平均時間復(fù)雜度為O(n) ,其中 為線性表的長度。例如,在一個長度為 100 的順序表中,如果要在第 50 個位置插入一個元素,就需要將第 50 個到第 100 個元素向后移動一位。

刪除操作:類似地,刪除操作如果不是刪除表尾元素,需要將刪除位置之后的元素依次向前移動一位,以填補刪除元素后留下的空位。其平均時間復(fù)雜度也為O(n) 。比如刪除一個長度為 80 的順序表中的第 30 個元素,就需要將第 31 個到第 80 個元素向前移動一位。

查詢操作:由于可以直接通過索引訪問數(shù)組元素,所以查詢指定位置元素的時間復(fù)雜度為O(1) 。而查詢某個特定值的元素時,可能需要遍歷整個順序表,在最壞情況下時間復(fù)雜度為O(n) 。例如,在一個存儲學(xué)生成績的順序表中,如果要查找成績?yōu)?90 分的學(xué)生,可能需要逐個比較所有學(xué)生的成績。

二、順序表

順序表是用一段物理地址連續(xù)的存儲單元依次存儲數(shù)據(jù)元素的線性結(jié)構(gòu),一般情況下采用數(shù)組存儲。在數(shù)組上完成 數(shù)據(jù)的增刪查改。

2.1定義一個類來表示順序表

class ArrayList<E> {
    // 存儲數(shù)據(jù)的數(shù)組
    private E[] data;
    // 記錄當(dāng)前順序表中元素的個數(shù)
    private int size;
    // 構(gòu)造函數(shù),初始化數(shù)組容量
    public ArrayList(int capacity) {
        data = (E[]) new Object[capacity];
        size = 0;
    }
}

這里的 data 數(shù)組就是用來存放順序表元素的核心容器,而 size 則用于追蹤實際存儲的元素數(shù)量。

2.2接口的實現(xiàn)

public class SeqList {
private int[] array;
private int size;
// 默認構(gòu)造方法
SeqList(){ }
// 將順序表的底層容量設(shè)置為initcapacity
SeqList(int initcapacity){ }
// 新增元素,默認在數(shù)組最后新增
public void add(int data) { }
// 在 pos 位置新增元素
public void add(int pos, int data) { }
// 判定是否包含某個元素
public boolean contains(int toFind) { return true; }
// 查找某個元素對應(yīng)的位置
public int indexOf(int toFind) { return -1; }
// 獲取 pos 位置的元素
public int get(int pos) { return -1; }
// 給 pos 位置的元素設(shè)為 value
public void set(int pos, int value) { }
//刪除第一次出現(xiàn)的關(guān)鍵字key
public void remove(int toRemove) { }
// 獲取順序表長度
public int size() { return 0; }
// 清空順序表
public void clear() { }
// 打印順序表,注意:該方法并不是順序表中的方法,為了方便看測試結(jié)果給出的
public void display() { }
}

插入操作

當(dāng)向順序表中插入一個元素時,情況會相對復(fù)雜一些。如果是在順序表的末尾插入元素,操作較為簡單,只需將元素放入 data[size] 的位置,并將 size 加 1 即可。但如果是在中間位置插入,例如在索引 k 處插入元素 e,則需要將索引 k 及之后的元素依次向后移動一位,為新元素騰出空間,然后再將新元素放入索引 k 處。

public void add(int index, E e) {
    if (index < 0 || index > size) {
        throw new IllegalArgumentException("Add failed. Illegal index.");
    }
    if (size == data.length) {
        resize(2 * data.length);
    }
    for (int i = size - 1; i >= index; i--) {
        data[i + 1] = data[i];
    }
    data[index] = e;
    size++;
}

刪除操作

刪除順序表中的元素同樣需要考慮多種情況。如果刪除的是末尾元素,直接將 size 減 1 即可。若刪除索引為 k 的元素,則需要將索引 k 之后的元素依次向前移動一位,覆蓋掉要刪除的元素。

public E remove(int index) {
    if (index < 0 || index >= size) {
        throw new IllegalArgumentException("Remove failed. Illegal index.");
    }
    E ret = data[index];
    for (int i = index + 1; i < size; i++) {
        data[i - 1] = data[i];
    }
    size--;
    data[size] = null;
    if (size == data.length / 4 && data.length / 2!= 0) {
        resize(data.length / 2);
    }
    return ret;
}

三、ArrayList的簡介

ArrayList是 Java 集合框架中的一個重要類,它位于java.util包中。它實現(xiàn)了List接口,這意味著它是一個有序的集合,允許存儲重復(fù)的元素。它的底層數(shù)據(jù)結(jié)構(gòu)是一個動態(tài)大小的數(shù)組,這使得它可以根據(jù)需要自動調(diào)整大小。

與普通數(shù)組相比,ArrayList更加靈活。普通數(shù)組在創(chuàng)建時就確定了大小,之后很難改變其容量,而ArrayList可以方便地添加或刪除元素,并且會自動處理數(shù)組容量的擴展和收縮。

說明:

1. ArrayList是以泛型?式實現(xiàn)的,使?時必須要先實例化

2. ArrayList實現(xiàn)了RandomAccess接?,表明ArrayList?持隨機訪問

3. ArrayList實現(xiàn)了Cloneable接?,表明ArrayList是可以clone的

4. ArrayList實現(xiàn)了Serializable接?,表明ArrayList是?持序列化的

5. 和Vector不同,ArrayList不是線程安全的,在單線程下可以使?,在多線程中可以選擇Vector或者 CopyOnWriteArrayList

6. ArrayList底層是?段連續(xù)的空間,并且可以動態(tài)擴容,是?個動態(tài)類型的順序表

創(chuàng)建ArrayList對象

要使用ArrayList,首先需要導(dǎo)入java.util.ArrayList類。

import java.util.ArrayList;
public class ArrayListExample {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
    }
}

創(chuàng)建了一個可以存儲String類型元素的ArrayList。其中是泛型參數(shù),用于指定列表中元素的類型。除了String,還可以是其他基本數(shù)據(jù)類型對應(yīng)的包裝類(如Integer、Double等)或自定義的類類型。

四、ArrayList使用

4.1 ArrayList的構(gòu)造

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);
// 避免省略類型,否則:任意類型的元素都可以存放,使?時將是?場災(zāi)難
List list4 = new ArrayList();
list4.add("111");
list4.add(100);
}

4.2 ArrayList常?操作

4.2.1添加元素

add(E e)方法:用于在ArrayList末尾添加元素。

import java.util.ArrayList;
public class ArrayListAddExample {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        System.out.println(fruits); 
    }
}

首先創(chuàng)建了一個ArrayList對象fruits,用于存儲String類型的元素。然后通過add方法添加了兩個水果名稱,最后打印出ArrayList,輸出結(jié)果為[Apple, Banana]。

add(int index, E e)方法:用于在指定索引index處插入元素e。

import java.util.ArrayList;
public class ArrayListAddAtIndexExample {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add(1, "Cherry");
        System.out.println(fruits); 
    }
}

這里在索引為1的位置插入了"Cherry",原來索引為1(即"Banana")及其后面的元素會向后移動一位。輸出結(jié)果為[Apple, Cherry, Banana]。

4.2.2獲取元素

get(int index)方法:用于獲取ArrayList中指定索引index處的元素。

import java.util.ArrayList;
public class ArrayListGetExample {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        String secondFruit = fruits.get(1);
        System.out.println(secondFruit); 
    }
}

通過get(1)獲取了索引為1的元素,即"Banana",并將其存儲在secondFruit變量中,最后打印輸出。

4.2.3修改元素

直接通過索引賦值:可以像操作數(shù)組一樣,通過指定索引來修改ArrayList中的元素。

import java.util.ArrayList;
public class ArrayListSetExample {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.set(1, "Orange");
        System.out.println(fruits); 
    }
}

通過set(1, “Orange”)將索引為1的元素(原來為"Banana")修改為"Orange",輸出結(jié)果為[Apple, Orange]。

4.2.4刪除元素

remove(int index)方法:用于刪除指定索引index處的元素。

import java.util.ArrayList;
public class ArrayListRemoveByIndexExample {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.remove(0);
        System.out.println(fruits); 
    }
}

通過remove(0)刪除了索引為0的元素(即"Apple"),輸出結(jié)果為[Banana]。

remove(Object o)方法:用于刪除指定的對象o。

import java.util.ArrayList;
public class ArrayListRemoveByObjectExample {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.remove("Apple");
        System.out.println(fruits); 
    }
}

通過remove(“Apple”)刪除了ArrayList中值為"Apple"的元素,輸出結(jié)果為[Banana]。

4.2.5遍歷ArrayList

使用普通for循環(huán)

import java.util.ArrayList;
public class ArrayListForLoopExample {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        for (int i = 0; i < fruits.size(); i++) {
            System.out.println(fruits.get(i));
        }
    }
}

在這個循環(huán)中,i從0開始,每次循環(huán)增加1,直到i小于ArrayList的大?。ㄍㄟ^size()方法獲?。?。在循環(huán)體內(nèi)部,通過get(i)方法獲取當(dāng)前索引的元素并打印輸出。

使用增強for循環(huán)(for - each循環(huán))

import java.util.ArrayList;
public class ArrayListForEachLoopExample {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        for (String fruit : fruits) {
            System.out.println(fruit);
        }
    }
}

fruit變量會依次獲取ArrayList中的每個元素,循環(huán)會自動遍歷整個ArrayList,直到所有元素都被訪問。

使用迭代器(Iterator):

import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListIteratorExample {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        Iterator<String> iterator = fruits.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

通過iterator()方法獲取ArrayList的迭代器。然后通過hasNext()方法檢查是否還有下一個元素,如果有,則通過next()方法獲取并打印下一個元素,直到?jīng)]有更多元素為止。

五、ArrayList的擴容機制

ArrayList是?個動態(tài)類型的順序表,即:在插?元素的過程中會?動擴容。

public boolean add(E e) {
	modCount++;
	add(e, elementData, size);
	return true;
}
private void add(E e, Object[] elementData, int s) {
	if (s == elementData.length) //第?次存儲的時候 elementData.length=0,s = 0
	elementData = grow();
	elementData[s] = e;
	size = s + 1;
}
private Object[] grow() {
	return grow(size + 1);
}
private Object[] grow(int minCapacity) {
	int oldCapacity = elementData.length;
	if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
		int newCapacity = ArraysSupport.newLength(oldCapacity,
		minCapacity - oldCapacity, /* minimum growth */
		oldCapacity >> 1 /* preferred growth */);
	return elementData = Arrays.copyOf(elementData, newCapacity);
	} else {
		return elementData = new Object[Math.max(DEFAULT_CAPACITY,minCapacity)];
	}
}
//oldLength: 當(dāng)前數(shù)組的?度
//minGrowth: 最?需要增加的?度
//prefGrowth: ?選的增? 度(通常是當(dāng)前??的?半)
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
	// preconditions not checked because of inlining
	// assert oldLength >= 0
	// assert minGrowth > 0
	//當(dāng)前?度加上 minGrowth 和 prefGrowth 中的較?值。
	int prefLength = oldLength + Math.max(minGrowth, prefGrowth); // might overflow
	if (0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH) {
		return prefLength;
	} else {
		// put code cold in a separate method
			return hugeLength(oldLength, minGrowth);
		}
}
private static int hugeLength(int oldLength, int minGrowth) {
	int minLength = oldLength + minGrowth;
	if (minLength < 0) { // overflow
		throw new OutOfMemoryError("Required array length " + oldLength + " + " + minGrowth + " is too large");
	} else if (minLength <= SOFT_MAX_ARRAY_LENGTH) {
		return SOFT_MAX_ARRAY_LENGTH;
	} else {
		return minLength;
			}
}

如果調(diào)?不帶參數(shù)的構(gòu)造?法,第?次分配數(shù)組??為10

后續(xù)擴容為1.5倍擴容

以上就是Java數(shù)據(jù)結(jié)構(gòu)之ArrayList與順序表詳解的詳細內(nèi)容,更多關(guān)于Java ArrayList與順序表的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java中的HashSet集合解析

    Java中的HashSet集合解析

    這篇文章主要介紹了Java中的HashSet集合解析,HashSet 實現(xiàn) Set 接口,內(nèi)部維護一個 HashMap 實例,它不能保證集合迭代的順序,也不能保證順序不變,HashSet 允許 null 元素,需要的朋友可以參考下
    2023-11-11
  • 詳解Java如何獲取文件編碼格式

    詳解Java如何獲取文件編碼格式

    這篇文章主要介紹了詳解Java如何獲取文件編碼格式,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-01-01
  • Java MapStruct解了對象映射的毒

    Java MapStruct解了對象映射的毒

    這篇文章主要介紹了MapStruct解了對象映射的毒,對MapStruct感興趣的同學(xué),可以參考下
    2021-04-04
  • Java集合去重導(dǎo)致的線上問題

    Java集合去重導(dǎo)致的線上問題

    這篇文章主要介紹了Java集合去重導(dǎo)致的線上問題,根據(jù)主題提出Set是怎樣保證數(shù)據(jù)的唯一性的,為什么兩種去重方式性能差距這么大的問題,下文解決思路需要的小伙伴可以參考一下
    2022-04-04
  • Java實現(xiàn)拖拽文件上傳dropzone.js的簡單使用示例代碼

    Java實現(xiàn)拖拽文件上傳dropzone.js的簡單使用示例代碼

    本篇文章主要介紹了Java實現(xiàn)拖拽文件上傳dropzone.js的簡單使用示例代碼,具有一定的參考價值,有興趣的可以了解一下
    2017-07-07
  • SpringCloud之監(jiān)控數(shù)據(jù)聚合Turbine的實現(xiàn)

    SpringCloud之監(jiān)控數(shù)據(jù)聚合Turbine的實現(xiàn)

    這篇文章主要介紹了SpringCloud之監(jiān)控數(shù)據(jù)聚合Turbine的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • SpringBoot實現(xiàn)事件監(jiān)聽(異步執(zhí)行)的示例代碼

    SpringBoot實現(xiàn)事件監(jiān)聽(異步執(zhí)行)的示例代碼

    事件監(jiān)聽是一種機制,可以定義和觸發(fā)自定義的事件,以及在應(yīng)用程序中注冊監(jiān)聽器來響應(yīng)這些事件,本文主要介紹了SpringBoot實現(xiàn)事件監(jiān)聽(異步執(zhí)行)的示例代碼,感興趣的可以了解一下
    2024-08-08
  • springboot 使用yml配置文件給靜態(tài)變量賦值教程

    springboot 使用yml配置文件給靜態(tài)變量賦值教程

    這篇文章主要介紹了springboot 使用yml配置文件給靜態(tài)變量賦值教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • Spring Boot ActiveMQ如何設(shè)置訪問密碼

    Spring Boot ActiveMQ如何設(shè)置訪問密碼

    這篇文章主要介紹了Spring Boot ActiveMQ如何設(shè)置訪問密碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • SpringBoot 請求參數(shù)忽略大小寫的實例

    SpringBoot 請求參數(shù)忽略大小寫的實例

    這篇文章主要介紹了SpringBoot 請求參數(shù)忽略大小寫的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01

最新評論