Java中關於泛型、包裝類及ArrayList的詳細教程
一、泛型
1.1 泛型類的定義
// 1. 尖括號 <> 是泛型的標志 // 2. E 是類型變量(Type Variable),變量名一般要大寫 // 3. E 在定義時是形參,代表的意思是 MyArrayList 最終傳入的類型,但現在還不知道 public class MyArrayList<E> { private E[] array; private int size; }
泛型類可以一次有多個類型變量,用逗號分割。
- 泛型是作用在編譯期間的一種機制,即運行期間沒有泛型的概念。
- 泛型代碼在運行期間,利用 Object 達到的效果(這裡不是很準確)。
- 泛型的意義:自動對類型進行檢查
1.2 泛型類的使用
示例:
class MyArrayList<E>{// <E>代表當前類是一個泛型類,此時的E就是一個占位符而已 private E[] elem; private int usedSize; public MyArrayList() { // this.elem = elem; this.elem = (E[])new Object[10];//這樣的寫法不是十分正確 } public void add(E val){ this.elem[usedSize] = val; usedSize++; } public E get(int pos){ return this.elem[pos]; } } public class test02 { public static void main(String[] args) { //泛型中尖括號裡面的內容不參與類型的組成 MyArrayList<String> myArrayList = new MyArrayList<>(); System.out.println(myArrayList); MyArrayList<Integer> myArrayList1 = new MyArrayList<>(); System.out.println(myArrayList1); MyArrayList<Boolean> myArrayList2 = new MyArrayList<>(); System.out.println(myArrayList2); } public static void main2(String[] args) { MyArrayList<String> myArrayList = new MyArrayList<>(); myArrayList.add("ni");//自動對類型進行檢查,不是字符串類型就會報錯 myArrayList.add("n"); String ret = myArrayList.get(1);//自動對類型進行強制類型轉換 System.out.println(ret); } }
1.3 泛型總結
- 泛型是為瞭解決某些容器、算法等代碼的通用性而引入,並且能在編譯期間做類型檢查。
- 泛型利用的是
Object
是所有類的祖先類,並且父類的引用可以指向子類對象的特定而工作。 - 泛型是一種編譯期間的機制,即
MyArrayList<Integer>
和MyArrayList<String>
在運行期間是一個類型。即泛型中尖括號裡面的內容不參與類型的組成。 - 泛型是
java
中的一種合法語法,標志就是尖括號<>
。
二、包裝類
2.1基本數據類型和包裝類直接的對應關系
基本數據類型 | 包裝類 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
基本就是類型的首字母大寫,除瞭 Integer
和 Character
。
2.2 包裝類的使用,裝箱(boxing)和拆箱(unboxing)
裝箱(裝包):把簡單類型變成包裝類型。 拆箱(拆包):把包裝類型變成簡單類型。
public static void main(String[] args) { Integer a = 123;//裝箱 裝包(隱式的) //Integer 的范圍[-128,127]; int b= a;//拆箱 拆包(隱式的) System.out.println("a="+a+" "+ "b="+ b); System.out.println("==============="); Integer a2 = Integer.valueOf(123);//顯式的裝包 Integer a3 = new Integer(123);//顯式的裝包 int b2 = a2.intValue();//顯式的拆包 double d = a2.doubleValue();//顯式的拆包 int i = 10;//顯式的初始化 }
2.3 自動裝箱(autoboxing)和自動拆箱(autounboxing)
在使用過程中,裝箱和拆箱帶來不少的代碼量,所以為瞭減少開發者的負擔,java 提供瞭自動機制。 自動裝箱和自動拆箱是工作在編譯期間的一種機制。
int b2 = a2.intValue();//顯式的拆包 double d = a2.doubleValue();//顯式的拆包
三、List 的使用
3.1 ArrayList簡介
在集合框架中,ArrayList是一個普通的類,實現瞭List接口,具體框架圖如下:
ArrayList
實現瞭RandomAccess
接口,表明ArrayList
支持隨機訪問。ArrayList
實現瞭Cloneable
接口,表明ArrayList
是可以clone
的。ArrayList
實現瞭Serializable
接口,表明ArrayList
是支持序列化的。- 和
Vector
不同,ArrayList
不是線程安全的,在單線程下可以使用,在多線程中可以選擇Vector或者CopyOnWriteArrayList
。 ArrayList
底層是一段連續的空間,並且可以動態擴容,是一個動態類型的順序表。 3.2 ArrayList的構造
public static void main(String[] args) { // ArrayList創建,推薦寫法 // 構造一個空的列表 List<Integer> list1 = new ArrayList<>(); // 構造一個具有10個容量的列表 List<Integer> list2 = new ArrayList<>(10); list2.add(1); list2.add(2); list2.add(3); // list2.add("hello"); // 編譯失敗,List<Integer>已經限定瞭,list2中隻能存儲整形元素 // list3構造好之後,與list2中的元素一致 //使用另外一個ArrayList對list3進行初始化 ArrayList<String> list3 = new ArrayList<>(list2); // 避免省略類型,否則:任意類型的元素都可以存放,使用時將是一場災難 List list4 = new ArrayList(); list4.add("111"); list4.add(100); }
3.3 ArrayList的遍歷
ArrayList
可以使用三種方式遍歷:for循環+下標
、foreach
、使用迭代器
。
public static void main(String[] args) { List<String> list = new ArrayList<>(); ArrayList<String> list2 = new ArrayList<>(); list2.add("hello"); list2.add("world"); System.out.println(list2);//打印方式一 System.out.println("============"); for (int i = 0; i < list2.size(); i++) {//打印方式二 System.out.print(list2.get(i)+" "); } System.out.println(); System.out.println("=========="); for (String s:list2) {//打印方式三 System.out.print(s+" "); } System.out.println(); System.out.println("====迭代器打印方式1======"); Iterator<String> it = list2.iterator(); while (it.hasNext()){ System.out.print(it.next()+" "); } System.out.println(); System.out.println("=====迭代器打印方式2====="); ListIterator<String> it2 = list2.listIterator();//打印方式四,使用迭代器進行打印 while (it2.hasNext()){ System.out.print(it2.next()+" "); } }
輸出結果:
3.4 ArrayList的常見操作
3.4.1 刪除 index 位置元素(remove)
E remove(int index) //刪除 index 位置元素
示例:
public static void main(String[] args) { ArrayList<String> list2 = new ArrayList<>(); list2.add("hello"); list2.add("bit"); list2.add("haha"); Iterator<String> it = list2.iterator(); while (it.hasNext()) { String ret = it.next(); if(ret.equals("hello")) { it.remove();//首先需要使用next方法迭代出集合中的元素 ,然後才能調用remove方法 }else { System.out.print(ret + " "); } } System.out.println(); System.out.println("========迭代器List相關打印=========="); ListIterator<String> it2 = list2.listIterator(); while (it2.hasNext()) { String ret = it2.next(); if(ret.equals("hello")) { it2.remove();//首先需要使用next方法迭代出集合中的元素 ,然後才能調用remove方法 }else { System.out.print(ret + " "); } } }
輸出結果:
3.4.1尾插(add)
boolean add(E e) //尾插 e
示例:
public static void main(String[] args) { ArrayList<String> list2 = new ArrayList<>(); //CopyOnWriteArrayList<String> list2 = new CopyOnWriteArrayList<>(); list2.add("hello"); list2.add("bit"); list2.add("haha"); //Iterator迭代器沒有add方法 /* Iterator<String> it = list2.iterator(); while (it.hasNext()) { String ret = it.next(); if(ret.equals("hello")) { it.add();//沒有add方法 }else { System.out.print(ret + " "); } }*/ //使用ListIterator迭代器的方法添加元素,會將元素添加到其緊跟著的後面 ListIterator<String> it2 = list2.listIterator(); while (it2.hasNext()) { String ret = it2.next(); if(ret.equals("bit")) { it2.add("world"); //若使用list2.add()就會拋出異常, //但是將上面的list2變成CopyOnWriteArrayList<String>類型就不會報錯。 //就可以使用list2.add()的方法就可以 // list2.add("world"); }else { System.out.print(ret + " "); } } System.out.println("================="); System.out.println(list2); }
運行結果:
ArrayList<String> list2 = new ArrayList<>();//不是線程安全的 迭代時使用的是it2.add("world"); CopyOnWriteArrayList<String> list2 = new CopyOnWriteArrayList<>();//是線程安全的 迭代時使用的是list2.add("world");
3.4.2將元素插入到list中的指定位置add
3.4.3 尾插一個ArrayList中的所有元素到另一個ArrayList當中(addAll)
方法:
void add(int index, E element) //將 e 插入到 index 位置 boolean addAll(Collection<? extends E> c) //尾插 c 中的元素
示例:
public static void main(String[] args) { ArrayList<String> list2 = new ArrayList<>(); list2.add("a"); list2.add("b"); list2.add("c"); list2.add("d"); list2.add("d"); System.out.println(list2);//add方法默認將字符串放到數組的最後一個位置 list2.add(0,"hello");//在list2的零下標位置加入字符串"hello" System.out.println(list2); ArrayList<String> list3 = new ArrayList<>(); list3.add("加入"); list2.addAll(list3);//將list3中的所有元素放到list2中 System.out.println(list2); }
輸出結果:
3.4.4 刪除指定下標位置的元素remove(int index)
3.4.5刪除list中第一次出現的某元素remove(Object o)
3.4.6 獲取某下標位置的元素get()
3.4.7 將指定下標位置的元素設置為指定值set()
方法:
E remove(int index) //刪除 index 位置元素 boolean remove(Object o) //刪除遇到的第一個 o E get(int index) //獲取下標 index 位置元素 E set(int index, E element) //將下標 index 位置元素設置為 element
示例:
public static void main(String[] args) { ArrayList<String> list2 = new ArrayList<>(); list2.add("a"); list2.add("b"); list2.add("c"); list2.add("d"); list2.add("d"); System.out.println(list2);//add方法默認放到數組的最後一個位置 String ret = list2.remove(0);//刪除0下標位置元素 System.out.println(list2); boolean ret1 = list2.remove("d"); //刪除遇到的第一個"d" //如果要刪除的數list2中沒有則返回false System.out.println(ret1); //true String ret2 = list2.get(2);//獲取下標為2位置的元素 System.out.println(ret2);//d String ret3 = list2.set(2,"hello");//將下標為2位置的元素改為"hello" System.out.println(ret3);//d System.out.println(list2);//[b, c, hello]
輸出結果:
3.4.8 清空線性表中的元素clear()
3.4.9 判斷線性表中是否包含某元素 contains()
3.4.10 返回第一個 o 所在下標位置 indexOf()
3.4.11 返回最後一個o出現的下標位置 lastIndexOf()
3.4.12 截取部分 list 中的部分元素 subList()
方法:
void clear() //清空 boolean contains(Object o) //判斷 o是否在線性表中 int indexOf(Object o) //返回第一個 o 所在下標 int lastIndexOf(Object o) //返回最後一個 o 的下標 List<E> subList(int fromIndex, int toIndex) //截取部分 list
示例:
public static void main(String[] args) { ArrayList<String> list2 = new ArrayList<>(); list2.add("a"); list2.add("b"); list2.add("c"); list2.add("d"); list2.add("d"); System.out.println(list2);//add方法默認放到數組的最後一個位置 System.out.println(list2.indexOf("a"));//0 判斷a的下標位置 System.out.println(list2.lastIndexOf("d"));//4 判斷最後一個d出現的下標位置 List<String> sub = list2.subList(1,3);//[b, c] 截取下標為[1,3)位置的元素,截取的區間范圍為左閉右開的 System.out.println(sub);//[b, c] System.out.println(list2);//[a, b, c, d, d] System.out.println("==================="); sub.set(0,"p"); System.out.println(sub);//[p, c] System.out.println(list2);//[a, p, c, d, d] System.out.println(list2.contains("c"));//true //判斷list2當中是否包含字符"c" list2.clear();//將list2中的元素清空 System.out.println(list2);
輸出結果:
四、ArrayList的擴容機制
如果ArrayList
調用不帶參數的構造方法,那麼順序表的大小為0
,當第一次add
的時候,整個順序表才變為瞭10
;當這個10
放滿瞭,開始擴容,以1.5
倍的方式進行擴容。 如果調用的是給定容量的構造方法,那麼順序表的大小就是給定的容量,放滿瞭還是以1.5
倍進行擴容。
到此這篇關於Java中關於泛型、包裝類及ArrayList的詳細教程的文章就介紹到這瞭,更多相關java泛型包裝類ArrayList內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Java中ArrayList與順序表的概念與使用實例
- Java中Iterator與ListIterator迭代的區別
- Java集合的Collection接口和List接口詳解
- Java ArrayList中存放引用數據類型的方式
- Java List的remove()方法踩坑