java數據結構集合復習之ArrayList與順序表

前言: 這是我最一年學習java的一部分的回顧總結

1.List

1.1什么是List?

在框架集合中,List是一個接口,繼承自Collection。
在這里插入圖片描述

Collection也是一個接口,該接口中規范了后序容器中常用的一些方法,具體如下所示
在這里插入圖片描述
在這里插入圖片描述

--------
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 位置元素設置為 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

站在數據結構的角度來看,List就是一個線性表,即n個具有相同類型元素的有限序列,在該序列上可以執行增刪改查以及變量等操作。

1.2 List的使用

List是個接口,并不能直接用來實例化
如果要使用,必須去實例化List的實現類

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;public class ListExample {public static void main(String[] args) {// 使用 ArrayList 實現類List<String> arrayList = new ArrayList<>();arrayList.add("Apple");arrayList.add("Banana");arrayList.add("Orange");System.out.println("ArrayList: " + arrayList);// 使用 LinkedList 實現類List<String> linkedList = new LinkedList<>();linkedList.add("Mango");linkedList.add("Kiwi");linkedList.add("Grape");System.out.println("LinkedList: " + linkedList);}
}

List 不能直接實例化是因為接口本身只是一種規范或契約,它定義了一組方法的簽名,但并沒有提供這些方法的具體實現。
接口的主要目的是為了實現多態性和代碼的解耦。通過定義接口,不同的類可以實現相同的接口,從而以統一的方式進行處理。 打個比方,想象 List
接口是一個菜譜,它只規定了要有哪些菜(方法),但沒有告訴你具體怎么做這些菜(方法的實現)。只有具體的廚師(實現類),比如 ArrayList
或者 LinkedList ,才能按照這個菜譜做出實際的菜肴(實現方法)。

ArrayList與順序表

2.1 線性表

線性表(linear list)是n個具有相同特性的數據元素的有限序列。 線性表是一種在實際中廣泛使用的數據結構,常見的線性表:順序表、鏈表、棧、隊列…
線性表在邏輯上是線性結構,也就說是連續的一條直線。但是在物理結構上并不一定是連續的,線性表在物理上存儲時,通常以數組和鏈式結構的形式存儲
在這里插入圖片描述

在這里插入圖片描述

2.2 順序表

順序表是用一段物理地址連續的存儲單元依次存儲數據元素的線性結構,一般情況下采用數組存儲。在數組上完成數據的增刪查改。

下面是手動實現一個順序表的實現

package com;import java.util.Arrays;public class SeqList {private int[] array;//記錄當前順序表當中 有多少個有效的數據private int size;private static final int INIT_CAPACITY = 5;// 默認構造方法 將順序表的底層容量設置為INIT_CAPACITYpublic SeqList(){this.array = new int[INIT_CAPACITY];}//判斷當前順序表是否滿了 注意在進行新增操作是都要考慮數組是否需要判斷滿表public boolean isFull(){//返回當前表中的元素個數與當前表的長度作比較若相等是ture,反之falsereturn size == array.length;}//給數組擴容 注意在進行新增操作是都要考慮數組是否需要擴容private void resize(){array = Arrays.copyOf(array,2*array.length);}// 新增元素,默認在數組最后新增public void add(int data){if (isFull()){resize();}this.array[size] = data;//將當前指針位置+1,每次新增操作都需要size++;}// 在 pos 位置新增元素public void add(int pos,int data){//判斷pos位置合不合法if (pos<0 || pos>this.size){throw new PosOutBoundsException("add 元素的時候,pos位置不合法!");}if(isFull()){resize();}for (int i = size-1; i >= pos; i--) {array[i+1] = array[i];}array[pos] = data;size++;}// 判定是否包含某個元素public boolean contains(int toFind) {for (int i = 0; i <this.size; i++) {if(array[i] == toFind){return true;}}return false;}// 查找某個元素對應的位置public int indexOf(int toFind) {for (int i = 0; i < this.size; i++) {if (array[i] == toFind){return i;}}return -1;}// 獲取 pos 位置的元素public int get(int pos) {if (pos<0 || pos>this.size){throw new PosOutBoundsException("pos位置不合法!");}return array[pos];}// 給 pos 位置的元素設為 valuepublic void set(int pos, int value) {if (pos<0 || pos>this.size){throw new PosOutBoundsException("pos位置不合法!");}this.array[pos] = value;}//刪除第一次出現的關鍵字keypublic void remove(int toRemove) {if (isEmpty()){return;}int index = indexOf(toRemove);if (index == -1){System.out.println("沒有你要刪除的數據");}for (int i = index; i < this.size-1; i++) {this.array[i] = this.array[i+1];}size--;}// 獲取順序表長度public int size() {return size;}// 清空順序表public void clear() {size=0;}// 打印順序表,注意:該方法并不是順序表中的方法,為了方便看測試結果給出的public void display() {for (int i = 0; i < this.size; i++) {System.out.println(this.array[i]+ " ");}}public boolean isEmpty(){return this.size == 0;}public static void main(String[] args) {SeqList seqList = new SeqList();seqList.add(1);seqList.add(2);seqList.add(3);seqList.add(4);seqList.add(1,10000);seqList.display();}
}

2.3 ArrayList的遍歷

ArrayList 可以使用三方方式遍歷:for循環+下標、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();}

在這里插入圖片描述
注意:

  1. ArrayList最常使用的遍歷方式是:for循環+下標 以及 foreach
  2. 迭代器是設計模式的一種

2.4ArrayList的擴容機制

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

private static final int DEFAULT_CAPACITY = 10;// 默認容量大小
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};// 默認空間
transient Object[] elementData; 存放元素的空間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);
// 調用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;
}

總結:

  1. 檢測是否真正需要擴容,如果是調用grow準備擴容
  2. 預估需要庫容的大小初步預估按照1.5倍大小擴容如果用戶所需大小超過預估1.5倍大小,則按照用戶所需大小擴容真正擴容之前檢測是否能擴容成功,防止太大導致擴容失敗
  3. 使用copyOf進行擴容

2.5 ArrayList的小練習

給定一個非負整數 numRows,生成「楊輝三角」的前 numRows 行。
楊輝三角
解法:

 public List<List<Integer>> generate(int numRows) {List<List<Integer>> allList = new ArrayList<>();for (int i = 0; i < numRows; i++) {List<Integer> list = new ArrayList<>();list.add(1);for (int j = 1; j < i; j++) {list.add(allList.get(i-1).get(j-1)+allList.get(i-1).get(j));}if(i != 0){list.add(1);}allList.add(list);}return allList;}

2.6ArrayList的問題及思考

問題:

  1. ArrayList底層使用連續的空間,任意位置插入或刪除元素時,需要將該位置后序元素整體往前或者往后搬移,故時間復雜度為O(N)
  2. 增容需要申請新空間,拷貝數據釋放舊空間,會有不小的消耗
  3. 增容一般是呈2倍的增長,勢必會有一定的空間浪費。例如當前容量為100,滿了以后增容到200,我們再繼續插入了5個數據,后面沒有數據插入了,那么就浪費了95個數據空間。

思考:
如何解決以上問題呢?

  1. 對于頻繁的插入或刪除元素 我們可以適合的數據結構,例如LinkedList。LinkedList底層使用鏈表實現,在鏈表中間進行插入和刪除操作的時間復雜度為 O(1),但它在隨機訪問元素時的性能相對較差。

  2. 針對增容帶來消耗的問題:
    如能預先估計集合可能需要存儲的元素數量,在創建ArrayList時指定合適的初始容量,可以減少擴容的次數。或者采用內存池技術:創建一個內存池來管理內存分配和釋放。當需要擴容時,從內存池中獲取預先分配好的合適大小的內存塊,而不是每次都進行新的內存申請和釋放操作。

  3. 關于增容導致的空間浪費問題:
    一種解決思路是使用自定義的動態數組實現,根據實際元素數量更精確地控制擴容策略,而非簡單地按照固定倍數擴容。例如,可以根據當前元素數量和一個預設的負載因子來決定是否擴容以及擴容的幅度。但這種方式需要自己實現動態數組的相關邏輯,增加了編程的復雜性

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/41362.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/41362.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/41362.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[pwn]靜態編譯

靜態編譯 1. 棧足夠大的情況下 程序在ida打開后&#xff0c;左側的函數欄目沒有紅色&#xff08;系統調用的函數&#xff09;&#xff0c;而只有一些靜態函數&#xff0c;通常這類文件的大小會必普通的pwn題程序要大得多。 這種靜態編譯的題沒有調用庫函數&#xff0c;也就沒…

百度云智能媒體內容分析一體機(MCA)建設

導讀 &#xff1a;本文主要介紹了百度智能云MCA產品的概念和應用。 媒體信息海量且復雜&#xff0c;采用人工的方式對視頻進行分析處理&#xff0c;面臨著效率低、成本高的困難。于是&#xff0c;MCA應運而生。它基于百度自研的視覺AI、ASR、NLP技術&#xff0c;為用戶提供音視…

Vue 性能革命:揭秘前端優化的終極技巧;Vue優化技巧,解決Vue項目卡頓問題

目錄 Vue優化路徑 一、使用key 二、使用凍結對象 三、使用函數式組件 四、使用計算屬性 五、使用非實時綁定的表單項 六、保持對象引用穩定 6.1、保持對象引用穩定定義 6.2、保持對象引用穩定與不穩定的例子 6.3、vue2判斷數據是否變化是通過hasChanged函數實現的 ①…

2024年【四川省安全員B證】考試及四川省安全員B證考試題

題庫來源&#xff1a;安全生產模擬考試一點通公眾號小程序 2024年【四川省安全員B證】考試及四川省安全員B證考試題&#xff0c;包含四川省安全員B證考試答案和解析及四川省安全員B證考試題練習。安全生產模擬考試一點通結合國家四川省安全員B證考試最新大綱及四川省安全員B證…

golang項目中gorm框架的配置和具體使用

最近在改造golang項目&#xff0c;從postgre數據庫遷移到達夢數據庫&#xff0c;我還想在改造后的項目使用 gorm 操作數據庫&#xff0c;保持較小的改動。查找了不少資料&#xff0c;最終從以下兩篇文章中借鑒了不少 1、Gorm 入門介紹與基本使用 這篇知乎文章詳細介紹了 gorm 框…

C語言 -- 操作符詳解?

C語言 -- 操作符詳解? 1. 操作符的分類2. 二進制和進制轉換?2.1 2進制轉10進制?2.1.1 10進制轉2進制數字? 2.2 2進制轉8進制和16進制?2.2.1 2進制轉8進制?2.2.2 2進制轉16進制? 3. 原碼、反碼、補碼?4. 移位操作符?4.1 左移操作符? 4.2 右移操作符?5. 位操作符&…

Symfony實戰手冊:PHP框架的高級應用技巧

引言 Symfony是一個功能強大且廣泛應用于PHP應用程序開發的框架&#xff0c;它提供了許多高級特性和工具&#xff0c;可以幫助開發人員更高效地構建和管理復雜的Web應用程序。以下是Symfony框架的幾個關鍵方面及其高級應用技巧&#xff1a; 1. 路由和控制器 Symfony的路由組…

suricata7 rule格式

suricata 7.0.5 suricata rule由三部分組成&#xff0c; action, header, options action,決定當前規則匹配上后需要執行的動作header,定義當前規則的協議&#xff0c;IP地址&#xff0c;端口&#xff0c;方向options,定義了具體的規則 一、 action 合法的action值有&#x…

Linux_共享內存通信

目錄 1、共享內存原理 2、申請共享內存 2.1 ftok 2.2 測試shmget、ftok 2.3 查看系統下的共享內存 3、關聯共享內存 3.1 測試shmat 4、釋放共享內存 4.1 測試shmctl 5、實現共享內存通信 6、共享內存的特性 結語 前言&#xff1a; 在Linux下&#xff0c;有一…

爆!Java高級特性之Stream API詳解

爆&#xff01;Java高級特性之Stream API詳解 Java 8引入的Stream API可以說是一個革命性的特性,讓我們告別了又臭又長的for循環,迎來了函數式編程的春天。今天就讓我們來一起深入了解這個讓人又愛又恨的Stream API吧! 什么是Stream? Stream就像一個高級的迭代器,允許我們以…

分支與循環

目錄 1. if語句 1&#xff09;if 2) else 3&#xff09;分支中包含多條語句 4&#xff09;if嵌套 2.關系操作符 3.條件操作符 4.邏輯操作符&#xff1a;&& || ! 1) 邏輯取反運算符 !?編輯 2 與運算符?編輯 3) 或運算符?編輯 4) 閏年的判斷 5) 短路 …

LangChain 概述 (模塊索引)

文章目錄 一、下載二、核心功能1、流式傳輸 streaming 三、LCEL四、組成部分1、Promp template2、Example selectors (示例選擇器)3、Chat models (聊天模型)4、Messages (消息)5、LLMs (大語言模型) 一、下載 二、核心功能 其中包括以下內容&#xff1a; 從模型中返回結構化的…

若依 Vue 前端分離 3.8.8 版中生成的前端代碼中關于下拉框只有下拉箭頭的問題

生成代碼修改前 <el-form-item label"課程學科" prop"subject"><el-select v-model"queryParams.subject" placeholder"請選擇課程學科" clearable><el-optionv-for"dict in course_subject":key"dict…

Mysql中常用函數的使用示例

場景 基礎知識回顧&#xff1a;mysql中常用函數的使用示例。 注&#xff1a; 博客&#xff1a;霸道流氓氣質-CSDN博客 實現 數學函數 -- ABS(x)返回x的絕對值 SELECT ABS(-1),ABS(2); -- PI()返回圓周率 SELECT PI(); -- SQRT(x)返回非負數x的二次方根 SELECT SQRT(4); -…

【博士每天一篇文獻-算法】Adult neurogenesis acts as a neural regularizer

閱讀時間&#xff1a;2023-12-20 1 介紹 年份&#xff1a;2022 作者&#xff1a;Lina M. Tran&#xff0c;Adam Santoro&#xff0c;谷歌DeepMind 期刊&#xff1a; Proceedings of the National Academy of Sciences 引用量&#xff1a;13 代碼&#xff1a;https://github.c…

A4-C四驅高防輪式巡檢機器人

在當今數字化和智能化迅速發展的時代&#xff0c;旗晟智能帶來了一款革命性的創新產品——A4-C四驅高防輪式巡檢機器人。這款機器人以其卓越的性能和多功能性&#xff0c;為工業巡檢領域帶來了全新的解決方案。 一、產品亮點 1、四驅動力與高防護設計 四驅高防輪式巡檢機器人…

ASUS/華碩槍神4 G532L G732L系列 原廠win10系統 工廠文件 帶F12 ASUS Recovery恢復

華碩工廠文件恢復系統 &#xff0c;安裝結束后帶隱藏分區&#xff0c;一鍵恢復&#xff0c;以及機器所有驅動軟件。 系統版本&#xff1a;Windows10 原廠系統下載網址&#xff1a;http://www.bioxt.cn 需準備一個20G以上u盤進行恢復 請注意&#xff1a;僅支持以上型號專用…

GPT-2怎么做翻譯任務?

首先需要知道的是GPT-2無論在訓練還是推理過程都是只使用了transformer decoder&#xff0c;并沒有使用encoder結構&#xff0c;那么它是怎么做的翻譯任務呢&#xff1f; 使用transformer encoderdecoder的著名架構有&#xff1a; 最原始的transformer model&#xff08;Atte…

計算機應用數學--第一次作業

第一次作業計算題編程題 &#xff08;20分&#xff09; 第一次作業 計算題 &#xff08;20分&#xff09;求 E ( X ) E(X) E(X)&#xff0c; V a r ( X ) Var(X) Var(X) &#xff08;1&#xff09; X X X 服從 [ a , b ] [a,b] [a,b] 均勻分布。 &#xff08;2&#xff09;…

操作系統期末必考概念大綱(整理·全)

第一章 1、 操作系統的概念 2、 計算機發展的四個階段 3、 手工操作階段、批處理系統階段、多道程序系統階段、分時操作系統階段、通用操作系統階段 4、 批處理系統&#xff08;聯機、脫機&#xff09; 5、 操作系統的6個基本類型 6、 多道批處理特征 7、 分時系統特點 8、 算法…