Java中ArrayList與LinkedList的使用及區(qū)別詳解
一、List
1.什么是List?
在集合框架中,List就是一個接口,繼承于Collection接口。
在數(shù)據(jù)結(jié)構(gòu)的角度,List就是一個線性表,即n個具有相同類型元素的有限序列,在該序列上可以執(zhí)行增刪查改以及變量等操作。
什么是線性表?
線性表是由n個具有相同類型元素組成的有限序列。線性表是一種常見的數(shù)據(jù)結(jié)構(gòu)。在邏輯上,線性表是一種線性結(jié)構(gòu),就是連續(xù)的一條直線,在物理結(jié)構(gòu)上,不一定是連續(xù)的,在物理存儲是,通常是以數(shù)組和鏈?zhǔn)?/strong>的結(jié)構(gòu)形式存儲。常見的線性比表有順序表、鏈表、棧、隊列.......
2.List中的常用方法
增 | |
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) | 刪除第一次出現(xiàn)的o元素 |
void clear() | 清空 |
查 | |
E get(int index) | 獲取index下標(biāo)位置元素 |
int indexOf(Object o) | 獲取第一個o元素所在的下標(biāo) |
int lastindexOf(Object o) | 獲取最后一個o元素所在的下標(biāo) |
boolean contains(Object o) | 查看是否包含o元素 |
改 | |
E set(int index,E Element) | 將index下標(biāo)的元素改為e |
截取 | |
List<E>subList(int formIndex,int toIndex) | 截取部分list |
List是一個接口,所以不能直接實例化。如果想要使用list接口,必須實例化list的實現(xiàn)類。
在集合框架中,ArrayList和LinkedList都實現(xiàn)了這個接口。
二、ArrayList
1.什么是ArrayList?
ArrayList是一個普通的類,是順序表的一種,實現(xiàn)了list接口,是一種可動態(tài)調(diào)整大小的數(shù)組,能夠儲存不同類型的對象。
什么是順序表?
順序表是用一段物理地址連續(xù)的存儲單元依次存儲數(shù)據(jù)元素的線性結(jié)構(gòu),一般情況下采用數(shù)組存儲。在數(shù)組上完成數(shù)據(jù)的增刪查改。
2.ArrayList的實例化
//接口的實例化: List<Integer> list1=new ArrayList<>(); //ArrayList的實例化: ArrayList<Integer> list=new ArrayList<>();
兩者區(qū)別:
- 接口的實例化:只能使用接口中定義類的方法;
- ArrayList實例化:可以使用ArrayList中獨有的方法,更具有靈活性
3.ArrayList的使用
ArrayList常見方法:
增: | |
void add(int data) | 在數(shù)組最后添加元素 |
void add(int pos,int data) | 在數(shù)組某下標(biāo)插入元素 |
刪: | |
void remove(int toRemove) | 刪除第一次出現(xiàn)的元素 |
void clear(); | 清空所有元素 |
查: | |
boolean contains(int toFind) | 查看是否包含該元素 |
int get(int pos) | 獲取該下標(biāo)元素 |
int indexOf(int toFind ) | 獲取該元素下標(biāo) |
改: | |
void set(int pos,int value) | 將下標(biāo)元素進(jìn)行更改 |
ArrayList方法的使用:
public static void main(String[] args) { List<Integer> list1=new ArrayList<>(); //增: //add:尾插 list1.add(1); list1.add(2); list1.add(3); list1.add(4); list1.add(5); System.out.println(list1);//[1, 2, 3, 4, 5] //add:任意位置插入 list1.add(3,100); System.out.println(list1);//[1, 2, 3, 100, 4, 5] //查: //contains:是否包含該元素 System.out.println(list1.contains(11));//false //get:獲取下標(biāo)元素 int ret=list1.get(3); System.out.println(ret);//100 //indexOf:獲取元素下標(biāo) int ret2=list1.indexOf(4); System.out.println(ret2);//4 //改 //set:將某下標(biāo)的元素進(jìn)行更改 list1.set(1,13); System.out.println(list1);//[1, 13, 3, 100, 4, 5] //刪: // remove:刪除第一次出現(xiàn)的元素 list1.remove(2); list1.remove(3); //list1.remove(6);//超出范圍,報錯 System.out.println(list1);//[1, 13, 100, 5] //清空 list1.clear(); System.out.println(list1);//無 //大小的獲?。? System.out.println(list1.size()); }
4.ArrayList的遍歷
ArrayList的遍歷可以使用三種方法:for循環(huán)、foreach、使用迭代器
示例:
public static void main(String[] args) { List<Integer> list1=new ArrayList<>(); list1.add(1); list1.add(2); list1.add(3); list1.add(4); list1.add(5); }
for循環(huán):
//for循環(huán)語句: //list1.size():list1長度 for (int i = 0; i < list1.size(); i++) { //get(i):獲取i下標(biāo)的元素 System.out.print(list1.get(i)+" ");//1 2 3 4 5 }
foreach語句:
//foreach: //每次循環(huán)時,取出list中的一個元素,將該元素賦值給變量num中 for (Integer num:list1) { System.out.print(num+" ");//1 2 3 4 5 }
迭代器:Iterator和ListIterator
//迭代器: //從前往后打印 // Iterator System.out.println("=====Iterator====="); Iterator<Integer> a=list1.iterator(); //a.hasNext():用于判斷集合a中是否還有下一個元素,如果有返回true,沒有返回false while(a.hasNext()){ //a.next:返回迭代器當(dāng)前所指向的元素,然后指向下一個元素未被遍歷的元素并打印 System.out.print(a.next()+" "); } System.out.println(); //listIterator System.out.println("=====listIterator====="); ListIterator<Integer> b=list1.listIterator(); while(b.hasNext()){ System.out.print(b.next()+" ");//1 2 3 4 5 } System.out.println(); System.out.println("=====listIterator====="); //從后往前打印 ListIterator<Integer> c=list1.listIterator(list1.size()); //b.hasPrevious():用于判斷集合a中是否有上一個元素,如果有返回true,沒有返回false while(b.hasPrevious()){ //b.previous:返回迭代器當(dāng)前所指向的元素,然后指向上一個元素未被遍歷的元素并打印 System.out.print(b.previous()+" ");//5 4 3 2 1 }
- ArrayList適合使用for循環(huán)語句遍歷;
Iterator和Listiterator的區(qū)別:
- Iterator是Java中的一個接口,通過hasNext()和next()方法實現(xiàn)順序遍歷;
- Listiterator是Iterator的子接口,除了擁有Iterator的方法外,還有其他功能,所以其還有雙向遍歷的功能,通過hasPrevious()和previous()來實現(xiàn)反向遍歷。
5.ArrayList特點
- 動態(tài)數(shù)組結(jié)構(gòu):基于數(shù)組實現(xiàn)。可以像普通數(shù)組一樣快速訪問元素;
- 動態(tài)調(diào)整大小:與普通數(shù)組不同,當(dāng)添加的元素個數(shù)大于ArrayList容量,ArrayList會自動擴(kuò)容1.5倍;
- 元素儲存有序:元素按照先后添加的順序在排序中,在插入或者刪除元素的時候,會相應(yīng)改變元素位置;
- 允許元素重復(fù):可以添加多個重復(fù)相同的元素;
- 通用性好:可以儲存各類對象。
6.ArrayList優(yōu)缺點
1.ArrayList的優(yōu)點:
- 快速訪問元素:基于數(shù)組實現(xiàn),可以快速訪問元素,時間復(fù)雜度為O(1);
- 內(nèi)存利用相對高效:內(nèi)存布局相對規(guī)整,主要是數(shù)組占用空間和少量額外空間用于記錄數(shù)組大小等信息。在不用頻繁的插入和刪除中間元素的情況下,內(nèi)存利用高效;
- 支持隨機訪問:可以隨機訪問任意位置的元素,在很多算法和操作中非常有用,如二分查找。
2.ArrayList的缺點:
- 擴(kuò)容開銷:當(dāng)元素數(shù)量大于數(shù)組容量的時候,會進(jìn)行擴(kuò)容。在擴(kuò)容時會創(chuàng)建一個新的容量更大的數(shù)組并復(fù)制舊元素,這會消耗較多的時間和資源;
- 插入和刪除的效率較低(中間元素):在頻繁的插入和刪除中間元素的時候,需要不斷地移動元素,時間復(fù)雜度為O(n)。
由于ArrayList不適合進(jìn)行頻繁的插入和刪除元素,所以在Java集合中引入了LinkedList,即鏈表結(jié)構(gòu)。
三、LinkedList
1.什么是LinkedList?
LinkedList的底層是雙向鏈表結(jié)構(gòu),是鏈表的一種。
什么是鏈表?
鏈表是一種常見的數(shù)據(jù)結(jié)構(gòu),它由一系列節(jié)點組成,每個節(jié)點包含數(shù)據(jù)域和指針域。鏈表邏輯順序是連續(xù)的,在物理存儲結(jié)構(gòu)是非連續(xù)的。
鏈表的分類:
有頭鏈表或者無頭鏈表:
- 有頭鏈表:有一個的頭節(jié)點,其指針指向第一個數(shù)據(jù)節(jié)點;
- 無頭鏈表:沒有專門的頭節(jié)點,第一個節(jié)點直接存儲數(shù)據(jù);
以下分類都有分為是否是有頭鏈表還是無頭鏈表:
- 單鏈表:每個節(jié)點包含數(shù)據(jù)和下一個接節(jié)點的指針,最后一個節(jié)點的指針指向空
- 雙鏈表:每個節(jié)點都有包含數(shù)據(jù),以及指向前一個節(jié)點的指針和指向后一個節(jié)點的指針
- 循環(huán)鏈表:循環(huán)鏈表分為單循環(huán)鏈表和雙循環(huán)鏈表,其就是最后一個節(jié)點的下一個節(jié)點的指針指向其頭結(jié)點。
2.LinkedList的實例化
LinkedList<Integer> list1=new LinkedList<>();
3.LinkedList的使用
其常用方法與ArrayList相差不大
public static void main(String[] args) { LinkedList<Integer> list1=new LinkedList<>(); //增: //add:尾插 list1.add(1); list1.add(2); list1.add(3); list1.add(4); list1.add(5); System.out.println(list1);//[1, 2, 3, 4, 5] //add:任意位置插入 list1.add(3,100); System.out.println(list1);//[1, 2, 3, 100, 4, 5] //查: //contains:是否包含該元素 System.out.println(list1.contains(11));//false //get:獲取下標(biāo)元素 int ret=list1.get(3); System.out.println(ret);//100 //indexOf:獲取元素下標(biāo) int ret2=list1.indexOf(4); System.out.println(ret2);//4 //改 //set:將某下標(biāo)的元素進(jìn)行更改 list1.set(1,13); System.out.println(list1);//[1, 13, 3, 100, 4, 5] //刪: // remove:刪除第一次出現(xiàn)的元素 list1.remove(2); list1.remove(3); //list1.remove(6);//超出范圍,報錯 System.out.println(list1);//[1, 13, 100, 5] //清空 list1.clear(); System.out.println(list1);//無 //大小的獲?。? System.out.println(list1.size());//0 }
4.LinkedList的遍歷
遍歷的三種方式:for循環(huán),foreach、迭代器
public static void main(String[] args) { LinkedList<Integer> list1=new LinkedList<>(); list1.add(1); list1.add(2); list1.add(3); list1.add(4); list1.add(5); //for循環(huán)語句: for (int i = 0; i < list1.size(); i++) { int ret=list1.get(i); System.out.print(ret+" ");//1 2 3 4 5 } System.out.println(); //foreach for (Integer x:list1) { System.out.print(x+" ");//1 2 3 4 5 } System.out.println(); //迭代器: Iterator<Integer> a=list1.iterator(); while (a.hasNext()){ System.out.print(a.next()+" ");//1 2 3 4 5 } System.out.println(); ListIterator b=list1.listIterator(); while (b.hasNext()){ System.out.print(b.next()+" ");//1 2 3 4 5 } System.out.println(); ListIterator c=list1.listIterator(list1.size()); while(c.hasPrevious()){ System.out.print(c.previous()+" ");//5 4 3 2 1 } }
- LinkedList適合使用迭代器遍歷;
5.ListedList的特點
- 動態(tài)性:沒有固定的大小限制,大小可動態(tài)變化;
- 插入或刪除高效:在插入和刪除時,只需修改相關(guān)節(jié)點即可,時間復(fù)雜度為O(1);
- 順序訪問:只能順序訪問節(jié)點,效率較低,時間復(fù)雜度為O(n);
- 存儲結(jié)構(gòu):由一系列節(jié)點組成,每個節(jié)點包含數(shù)據(jù)域和指針域;
- 通用性:可以存儲不同數(shù)據(jù)。
6.LinkedList優(yōu)缺點
1.LinkedList優(yōu)點:
- 動態(tài)性強:節(jié)點分散存儲,不受連續(xù)空間的限制;
- 插入或刪除高效:在插入和刪除時,只需修改相關(guān)節(jié)點即可,時間復(fù)雜度為O(1);
- 可擴(kuò)性好:可方便的增加和減少節(jié)點的數(shù)量;
2.LinkedList缺點:
- 隨機訪問效率低:只能順序訪問節(jié)點,效率較低,時間復(fù)雜度為O(n);
- 額外空間開銷大:除了存儲數(shù)據(jù)本身,每個節(jié)點還要存儲額外的指針信息,內(nèi)存利用率低;
- 數(shù)據(jù)存儲不連續(xù):不利于有效存儲,導(dǎo)致數(shù)據(jù)訪問慢;
四、ArrayList與LinkedList的區(qū)別
不同點 | ArrayList | LinkedList |
數(shù)據(jù)結(jié)構(gòu) | 邏輯上和物理上都是連續(xù)的 | 在邏輯上連續(xù),物理上不連續(xù) |
隨機訪問 | 隨機訪問效率快, 時間復(fù)雜度為O(1) | 隨機訪問效率慢, 時間復(fù)雜度為O(n) |
插入或刪除 | 效率慢, 時間復(fù)雜度為O(n) | 效率快, 時間復(fù)雜度為O(1) |
容量 | 空間不夠需要擴(kuò)容 | 沒有容量限制 |
內(nèi)存占用 | 內(nèi)存利用相對高效 | 內(nèi)存利用率低 |
應(yīng)用場景 | 元素訪問+高效存儲 | 插入和刪除頻繁 |
總結(jié)
到此這篇關(guān)于Java中ArrayList與LinkedList的使用及區(qū)別的文章就介紹到這了,更多相關(guān)Java ArrayList與LinkedList詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot 中的 CommandLineRunner 原理及使用示例
CommandLineRunner 是 Spring Boot 提供的一個非常有用的接口,可以幫助你在應(yīng)用程序啟動后執(zhí)行初始化任務(wù),本文通過多個示例詳細(xì)介紹了如何在實際項目中使用 CommandLineRunner,感興趣的朋友一起看看吧2025-04-04Maven中exec插件執(zhí)行Java程序的實現(xiàn)
在Maven項目中,可以使用Maven的插件來執(zhí)行Java程序,本文主要介紹了Maven中exec插件執(zhí)行Java程序的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2023-12-12java中@ConfigurationProperties失效的問題解決
在Java開發(fā)中,使用@ConfigurationProperties注解讀取配置文件時,如果配置類中的屬性設(shè)置為static,將無法正確讀取配置值,本文就來介紹一下具體解決方法,感興趣的可以了解一下2024-09-09IntelliJ IDEA基于Scala實現(xiàn)Git檢查工具
這篇文章主要介紹了如何使用Scala實現(xiàn)自定義的Git檢查工具,大家可以基于本文的示例進(jìn)行擴(kuò)展與實現(xiàn),也可以進(jìn)行其他應(yīng)用方向的嘗試,感興趣的可以了解下2023-08-08