Java中ArrayList與順序表的概念與使用實(shí)例
前言
通過(guò)前面的博客我們已經(jīng)大致了解了關(guān)于Java的基本知識(shí),而下面的幾篇博客我們著重開(kāi)始對(duì)于數(shù)據(jù)結(jié)構(gòu)的知識(shí)進(jìn)行學(xué)習(xí),這篇博客我們就了解關(guān)于順序表和ArrayList的相關(guān)知識(shí),從名字上我們就可以看到ArrayList是數(shù)組鏈表,也就是我們總說(shuō)的順序表。這是Java內(nèi)置的,因此不需要我們寫(xiě),這也方便了程序員的使用。那么面我們就來(lái)了解一下ArrayList順序表的相關(guān)知識(shí)。
在學(xué)習(xí)順序表之前呢,我們需要了解幾個(gè)概念。
泛型(Generic)
泛型的引入
問(wèn)題: 我們?cè)谥皩W(xué)習(xí)順序表的時(shí)候,只能保存int類型的元素,如果現(xiàn)在我們需要保存Person類型對(duì)象的引用順序表,那么我們?cè)撊绾谓鉀Q呢?
回答:
- 首先,我們?cè)趯W(xué)習(xí)多態(tài)過(guò)程中已知一個(gè)前提,基類的引用可以指向子類的對(duì)象。
- 其次,我們也已知Object是 java 中所有類的祖先類。
那么,解決這個(gè)問(wèn)題我們就想到一個(gè)辦法,我們將順序表數(shù)組種元素類型定義為Object類型,這樣我們的Object類型的引用可以指向int類型的對(duì)象,也可以指向Person類型的對(duì)象。舉個(gè)例子:
public class MyArrayList {
private Object[] array; // 保存順序表的元素,即 Object 類型的引用
private int size; // 保存順序表內(nèi)數(shù)據(jù)個(gè)數(shù)
public void add(Object o) {
尾插
}
public Object get(int index) {
獲取 index 位置的元素
}
...
}
現(xiàn)在的 MyArrayList 雖然可以做到添加任意類型的引用到其中了,但遇到以下代碼就會(huì)產(chǎn)生問(wèn)題。
Person person = (Person)books.get(0); // 將 Object 類型轉(zhuǎn)換為 Person 類型,需要類型轉(zhuǎn)換才能成功 // 這里編譯正確,但運(yùn)行時(shí)會(huì)拋出異常 ClassCastException
此時(shí)的book對(duì)象的get()方法的返回值是Object類型因此我們需要強(qiáng)制轉(zhuǎn)化為Person類型才可以賦值給person對(duì)象,但是這只是編譯上通過(guò),但是運(yùn)行仍會(huì)報(bào)錯(cuò),因此引入了泛型這個(gè)概念。
泛型的基本概念
泛型分為兩類:
- 泛型類
- 泛型方法
什么是泛型類呢?我們來(lái)看一個(gè)例子:
public class MyArrayList<E> {
private E[] array;
private int size;
...
}
在這個(gè)MyArrayList類中,我們可以看到后面跟了一個(gè)尖括號(hào),這就是泛型的標(biāo)志。有以下幾點(diǎn)需要注意:
- 尖括號(hào) <> 是泛型的標(biāo)志。
- E 是類型變量(Type Variable),變量名一般要大寫(xiě)。
- E 在定義時(shí)是形參,代表的意思是 MyArrayList 最終傳入的類型,但現(xiàn)在還不知道。
也就是說(shuō)我們?cè)谟眠@個(gè)類創(chuàng)建對(duì)象時(shí),我們可以在類的尖括號(hào)中告訴編譯器你使用的是什么對(duì)象。比如:
// 定義了一個(gè)元素是 Book 引用的 MyArrayList MyArrayList<Book> books = new MyArrayList<Book>(); books.add(new Book()); // 會(huì)產(chǎn)生編譯錯(cuò)誤,Person 類型無(wú)法轉(zhuǎn)換為 Book 類型 books.add(new Person()); // 不需要做類型轉(zhuǎn)換 Book book = book.get(0); // 不需要做類型轉(zhuǎn)換 // 會(huì)產(chǎn)生編譯錯(cuò)誤,Book 類型無(wú)法轉(zhuǎn)換為 Person 類型 Person person = book.get(0);
我們可以看到,MyArrayList存放的是Book類型的引用,這是編譯器就可以達(dá)到類似Object的效果,存儲(chǔ)Book類型的對(duì)象,如果在里面又想放入Person類型的對(duì)象就會(huì)報(bào)錯(cuò)。
總結(jié)
- 泛型是為了解決某些容器、算法等代碼的通用性而引入,并且能在編譯期間做類型檢查。
- 泛型利用的是 Object 是所有類的祖先類,并且父類的引用可以指向子類對(duì)象的特定而工作。
- 泛型是一種編譯期間的機(jī)制,即 MyArrayList< Person > 和MyArrayList< Book > 在運(yùn)行期間是一個(gè)類型。
- 泛型是 java 中的一種合法語(yǔ)法,標(biāo)志就是尖括號(hào) <>。
包裝類(Wrapper Class)
包裝類的引入
我們知道Object引用可以指向任意類型的對(duì)象,但是8種基本數(shù)據(jù)類型又不是對(duì)象,那么泛型就無(wú)法對(duì)這8種基本數(shù)據(jù)類型失效了。因此為了解決這個(gè)問(wèn)題java 引入了一類特殊的類,即這 8 種基本數(shù)據(jù)類型的包裝類,在使用過(guò)程中,會(huì)將類似int這樣的值包裝到一個(gè)對(duì)象中去。
基本數(shù)據(jù)類型與包裝類的對(duì)應(yīng)關(guān)系
| 基本數(shù)據(jù)類型 | 包裝類 |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
基本就是類型的首字母大寫(xiě),除了 Integer 和 Character。
ArrayList與順序表
ArrayList簡(jiǎn)介
簡(jiǎn)單了解了泛型和包裝類的知識(shí),下面我們就正式學(xué)習(xí)ArrayList的相關(guān)知識(shí)。
在集合框架中,ArrayList是一個(gè)普通的類,實(shí)現(xiàn)了List接口,具體框架圖如下:

說(shuō)明:
- ArrayList實(shí)現(xiàn)了RandomAccess接口,表明ArrayList支持隨機(jī)訪問(wèn)。
- ArrayList實(shí)現(xiàn)了Cloneable接口,表明ArrayList是可以clone的。
- ArrayList實(shí)現(xiàn)了Serializable接口,表明ArrayList是支持序列化的。
- 和Vector不同,ArrayList不是線程安全的,在單線程下可以使用,在多線程中可以選擇Vector或者CopyOnWriteArrayList。
- ArrayList底層是一段連續(xù)的空間,并且可以動(dòng)態(tài)擴(kuò)容,是一個(gè)動(dòng)態(tài)類型的順序表。
ArrayList使用
ArrayList的構(gòu)造
| 方法 | 解釋 |
|---|---|
| ArrayList() | 無(wú)參構(gòu)造 |
| ArrayList(Collection<? extends E> c) | 利用其他 Collection 構(gòu)建 ArrayList |
| ArrayList(int initialCapacity) | 指定順序表初始容量 |
舉個(gè)例子:
public static void main(String[] args) {
// ArrayList創(chuàng)建,推薦寫(xiě)法
// 構(gòu)造一個(gè)空的列表
List<Integer> list1 = new ArrayList<>();
// 構(gòu)造一個(gè)具有10個(gè)容量的列表
List<Integer> list2 = new ArrayList<>(10);
list2.add(1);
list2.add(2);
list2.add(3);
// list2.add("hello"); // 編譯失敗,List<Integer>已經(jīng)限定了,list2中只能存儲(chǔ)整形元素
// list3構(gòu)造好之后,與list中的元素一致
ArrayList<Integer> list3 = new ArrayList<>(list2);
// 避免省略類型,否則:任意類型的元素都可以存放,使用時(shí)將是一場(chǎng)災(zāi)難
List list4 = new ArrayList();
list4.add("111");
list4.add(100);
}
ArrayList常見(jiàn)方法
| 方法 | 解釋 |
|---|---|
| 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) | 刪除遇到的第一個(gè) o |
| E get(int index) | 獲取下標(biāo) index 位置元素 |
| E set(int index, E element) | 將下標(biāo) index 位置元素設(shè)置為 element |
| void clear() | 清空 |
| boolean contains(Object o) | 判斷 o 是否在線性表中 |
| int indexOf(Object o) | 返回第一個(gè) o 所在下標(biāo) |
| int lastIndexOf(Object o) | 返回最后一個(gè) o 的下標(biā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("測(cè)試課程");
System.out.println(list);
// 獲取list中有效元素個(gè)數(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)一往后搬移一個(gè)位置
list.add(1, "Java數(shù)據(jù)結(jié)構(gòu)");
System.out.println(list);
// 刪除指定元素,找到了就刪除,該元素之后的元素統(tǒng)一往前搬移一個(gè)位置
list.remove("JVM");
System.out.println(list);
// 刪除list中index位置上的元素,注意index不要超過(guò)list中有效元素個(gè)數(shù),否則會(huì)拋出下標(biāo)越界異常
list.remove(list.size()-1);
System.out.println(list);
// 檢測(cè)list中是否包含指定元素,包含返回true,否則返回false
if(list.contains("測(cè)試課程")){
list.add("測(cè)試課程");
}
// 查找指定元素第一次出現(xiàn)的位置:indexOf從前往后找,lastIndexOf從后往前找
list.add("JavaSE");
System.out.println(list.indexOf("JavaSE"));
System.out.println(list.lastIndexOf("JavaSE"));
// 使用list中[0, 4)之間的元素構(gòu)成一個(gè)新的ArrayList返回
List<String> ret = list.subList(0, 4);
System.out.println(ret);
list.clear();
System.out.println(list.size());
}
運(yùn)行結(jié)果:

ArrayList的遍歷
ArrayList 可以使用三方方式遍歷:for循環(huán)+下標(biāo)、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);
// 使用下標(biāo)+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();
}
運(yùn)行結(jié)果:

關(guān)于ArrayList順序表的相關(guān)知識(shí)就是這么多,ArrayList使用起來(lái)是比較簡(jiǎn)單的,但是細(xì)節(jié)上也是非常多的,而且還有一些其他的方法,我們可以通過(guò)源碼分析來(lái)看如何使用.
總結(jié)
到此這篇關(guān)于Java中ArrayList與順序表的文章就介紹到這了,更多相關(guān)Java ArrayList與順序表內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java基礎(chǔ)之隱式轉(zhuǎn)換vs強(qiáng)制轉(zhuǎn)換
這篇文章主要介紹了Java基礎(chǔ)之隱式轉(zhuǎn)換vs強(qiáng)制轉(zhuǎn)換的相關(guān)資料,需要的朋友可以參考下2015-12-12
java復(fù)制文件和java移動(dòng)文件的示例分享
本文主要介紹了java將文件夾下面的所有的jar文件拷貝到指定的文件夾下面的方法,需要的朋友可以參考下2014-02-02
Mybatis-Plus開(kāi)發(fā)提速器generator的使用
本文就介紹這款基于Mybatis-Plus的代碼自助生成器,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07

