Java數(shù)據(jù)結(jié)構(gòu)之List的使用總結(jié)

泛型
什么是泛型
泛型:即通過參數(shù)化類型來實現(xiàn)在同一份代碼上操作多種數(shù)據(jù)類型。泛型是在C#2.0引入的。泛型(Genericity)的字面意思是指具有在多種數(shù)據(jù)類型上皆可操作的含意,與模板有些相似。
優(yōu)點:泛型類和泛型方法同時具備可重用性、類型安全和效率,這是非泛型類和非泛型方法無法具備的。泛型通常用與集合以及作用于集合的方法一起使用。
泛型的分類
- 泛型類
- 泛型方法
泛型的定義簡單演示
- 1. 尖括號 <> 是泛型的標(biāo)志
- 2. E 是類型變量(Type Variable),變量名一般要大寫
- 3. E 在定義時是形參,代表的意思是 MyArrayList 最終傳入的類型,但現(xiàn)在還不知道
public class MyArrayList<E> {
private E[] array;
private int size;
...
}
泛型背后作用時期和背后的簡單原理
- 泛型是作用在編譯期間的一種機制,即運行期間沒有泛型的概念。
- 泛型代碼在運行期間,就是我們上面提到的,利用 Object 達(dá)到的效果(這里不是很準(zhǔn)確,后期會專門寫一篇博客講泛型)。
- < T > 代表當(dāng)前類是一個泛型類。
- new T[10]; 不能new泛型類型的數(shù)組 T[] t = new T[];
- 泛型的意義: ①在存儲元素的時候,可以自動進(jìn)行類型檢查 ②在獲取元素的時候,可以進(jìn)行自動類型的轉(zhuǎn)換
- 泛型類型的參數(shù):不能是簡單類型
- 泛型類型的參數(shù),是不參與類型的組成的
面試問題:
泛型到底是怎么編譯的?
1、泛型只在編譯的時候,起作用。在運行的時候,是沒有泛型的概念的?。?!
2、擦除機制 -> Object -> 不嚴(yán)謹(jǐn)-> 我們可以給定一個擦除邊界
泛型類的使用
// 定義了一個元素是 Book類 引用的 MyArrayList MyArrayList<Book> books = new MyArrayList<Book>(); books.add(new Book()); // 會產(chǎn)生編譯錯誤,Person 類型無法轉(zhuǎn)換為 Book 類型 books.add(new Person()); // 不需要做類型轉(zhuǎn)換 Book book = book.get(0); // 會產(chǎn)生編譯錯誤,Book 類型無法轉(zhuǎn)換為 Person 類型 Person person = book.get(0);
通過以上代碼,我們可以看到泛型類的一個使用方式:只需要在所有類型后邊跟尖括號,并且尖括號內(nèi)是人為限定所需要傳入的類型,即 E 可以看作的最后的類型。
注意:
- Book 只能想象成 E 的類型,但實際上 E 的類型還是 Object。
- Java中的泛型僅僅是一個編譯時的概念,在運行時,所有的泛型信息都被消除了,這被稱為泛型擦除。
泛型總結(jié)
- 泛型是為了解決某些容器、算法等代碼的通用性而引入,并且 能在編譯期間做類型檢查,如果用使用Object類,當(dāng)傳入了非法參數(shù)時,編譯器是不會報錯的。
- 泛型利用的是 Object 是所有類的祖先類,并且父類的引用可以指向子類對象的特定而工作。
- 泛型是一種編譯期間的機制,即
MyArrayList<Person>和MyArrayList<Book>在運行期間是一個類型。 - 泛型是 java 中的一種合法語法,標(biāo)志就是尖括號 < >
包裝類
Object 引用可以指向任意類型的對象,但有例外出現(xiàn)了,8 種基本數(shù)據(jù)類型不是對象,那豈不是剛才的泛型機制要失效了?
實際上也確實如此,為了解決這個問題,java 引入了一類特殊的類,即這 8 種基本數(shù)據(jù)類型的包裝類,在使用過程中,會將類似 int 這樣的值包裝到一個對象中去
基本數(shù)據(jù)類型和包裝類直接的對應(yīng)關(guān)系
| 基本數(shù)據(jù)類型 | 包裝類 |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
基本就是類型的首字母大寫,除了 Integer 和 Character。
包裝類的使用,裝箱(boxing)和拆箱(unboxing)
有手動裝箱 也有 自動裝箱,拆箱 也一樣

可以看到在使用過程中,裝箱和拆箱帶來不少的代碼量,所以為了減少開發(fā)者的負(fù)擔(dān),java 提供了自動機制。
注意:自動裝箱和自動拆箱是工作在編譯期間的一種機制
List的使用
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) | 刪除遇到的第一個 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) | 返回第一個 o 所在下標(biāo) |
| int lastIndexOf(Object o) | 返回最后一個 o 的下標(biāo) |
| List subList(int fromIndex, int toIndex) | 截取部分 list |
使用示例
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
public class ListDemo {
public static void main(String[] args) {
List<String> courses = new ArrayList<>();
courses.add("Kobe");
courses.add("Jordan");
courses.add("Westbrook");
courses.add("Durant");
// 和數(shù)組一樣,允許添加重復(fù)元素
courses.add("Kobe");
// 按照添加順序打印
System.out.println(courses);
// 類似數(shù)組下標(biāo)的方式訪問
System.out.println(courses.get(0));
//給目標(biāo)位置設(shè)置新元素
courses.set(0, "Jordan");
System.out.println(courses);
// 截取部分 [1, 3) 注意這里是左開右閉區(qū)區(qū)間
List<String> subCourses = courses.subList(1, 3);
System.out.println(subCourses);
// 重新構(gòu)造
List<String> courses2 = new ArrayList<>(courses);
System.out.println(courses2);
List<String> courses3 = new LinkedList<>(courses);
System.out.println(courses3);
// 引用的轉(zhuǎn)換
ArrayList<String> courses4 = (ArrayList<String>)courses2;
System.out.println(courses4);
//LinkedList<String> c = (LinkedList<String>)course2; 錯誤的類型
LinkedList<String> courses5 = (LinkedList<String>)courses3;
System.out.println(courses5);
//ArrayList<String> c = (ArrayList<String>)course3; 錯誤的類型
}
}
運行結(jié)果如下:

自動發(fā)牌案例
分為三個java文件

import java.util.ArrayList;
import java.util.List;
public class TestDemo {
public static void main(String[] args) {
List<Card> deck = CardDemo.buyDeck();
System.out.println("買來的新牌");
System.out.println(deck);
System.out.println("===========================");
CardDemo.shuffle(deck);
System.out.println("洗過后的牌");
System.out.println(deck);
System.out.println("===========================");
//三個人,每個人輪流抓牌,一個人五張牌
List<List<Card>> hands = new ArrayList<>();//二維數(shù)組的思維
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));
//這里的remove返回順序表里被移除的元素,剛好牌堆里少一張牌
}
}
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));
}
}
public class Card {
private int rank;//牌值
private String suit;//花色
public Card(int rank, String suit) {
this.rank = rank;
this.suit = suit;
}
@Override
public String toString() {
return String.format("[%s %d]", suit, rank);
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class CardDemo {
private static final String[] suits = {"?", "?", "?", "?"};
//買一副牌
public 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;
deck.add(new Card(rank, suit));//順序表默認(rèn)是尾插
}
}
return deck;
}
public static void swap(List<Card> deck, int i, int j) {
Card temp = deck.get(i);
deck.set(i, deck.get(j));
deck.set(j, temp);
}
public static void shuffle(List<Card> deck){
Random rand = new Random(20211122);
for (int i = deck.size() - 1; i > 0; i--){
int r = rand.nextInt(i);//生成0~i的隨機正整數(shù)
swap(deck, i ,r);
}
}
????????????????????????????????????????????????????
??原創(chuàng)不易,如有錯誤,歡迎評論區(qū)留言指出,感激不盡?
? 如果覺得內(nèi)容不錯,給個三連不過分吧~ ?
? 看到會回訪~ ?
????????????????????????????????????????????????????
到此這篇關(guān)于Java數(shù)據(jù)結(jié)構(gòu)之List的使用總結(jié)的文章就介紹到這了,更多相關(guān)Java List內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring?Boot獲取resources目錄下的文件三種方式詳解
在Spring?Boot項目中,經(jīng)常需要獲取resources目錄下的文件,這些文件可以包括配置文件、模板文件、靜態(tài)資源等,這篇文章主要介紹了Spring?Boot獲取resources目錄下的文件的三種方式,需要的朋友可以參考下2023-06-06
SpringMVC實現(xiàn)Controller的三種方式總結(jié)
這篇文章主要介紹了SpringMVC實現(xiàn)Controller的三種方式總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02
springboot?vue測試前端項目管理列表分頁功能實現(xiàn)
這篇文章主要為大家介紹了springboot?vue測試前端項目列表分頁功能實現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
java 反射getClass .class 的使用方法示例
這篇文章主要介紹了java 反射getClass .class 的使用方法,結(jié)合實例形式分析了java類反射機制的相關(guān)操作技巧,需要的朋友可以參考下2019-11-11
Spring注解@Resource和@Autowired區(qū)別對比詳解
這篇文章主要介紹了Spring注解@Resource和@Autowired區(qū)別對比詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09
SpringBoot Event 事件如何實現(xiàn)異步延遲執(zhí)行
這篇文章主要介紹了Spring Boot Event 事件如何實現(xiàn)異步延遲執(zhí)行問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02
Spring boot項目redisTemplate實現(xiàn)輕量級消息隊列的方法
這篇文章主要給大家介紹了關(guān)于Spring boot項目redisTemplate實現(xiàn)輕量級消息隊列的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Spring boot具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
java基于雙向環(huán)形鏈表解決丟手帕問題的方法示例
這篇文章主要介紹了java基于雙向環(huán)形鏈表解決丟手帕問題的方法,簡單描述了丟手帕問題,并結(jié)合實例形式給出了Java基于雙向環(huán)形鏈表解決丟手帕問題的步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-11-11

