
4 同步視圖(線程安全的視圖)
典型示例:Collections.synchronizedMap(map);
怎麼做到把線程不不安全改成線程安全的呢?在每塊可能造成同步問題的線程,都使用同步代碼塊包裹:
小總結:
📌同步操作也可以類似前面的異常操作對類進行擴充
5 被檢驗視圖
典型示例:List<String> list = Collections.checkedList(strings,String.class);
全部源自這個 typeCheck()和checkedCopyOf()
typeCheck():直接檢查對象是否能轉換為指定類型
checkedCopyOf():通過複制到泛型類數組,檢查是否會抛異常
小總結:
📌類型檢查操作也可以類似前面的異常、同步操作對類進行擴充
6 可選操作說明
視圖不能夠完全代替普通集合,隻是一些正常操作,以及進行不恰當操作時的異常說明。
視圖類可能沒有很好的實作接口有些操作上隻是寫了幾個,其他直接抛異常。
對于接口的方法總是覆寫不完全的處理方法:
📌使用類似前面元件一樣的擴充卡,先使用統一的抽象類實作所有方法,其他類在通過繼承這個類選用适合自己的方法
📌高版本 JDK 可以考慮直接使用預設方法,寫在接口類總
📌對于這部分公共代碼書寫内容又長又多的情況,建議直接使用模闆類
13.3.2 批量處理
典型示例:set.addAll(t);
set中添加集合 t 中的所有元素
典型示例2:set.removeAll(t);
set中删除集合 t 中的所有元素
特别需要注意的是,這些add/remove的操作,是會影響 原數組的,因為它并不是 Collections.retainAll(a,b) 這種格式的,也沒有額外傳回一個的集合
13.3.3 集合與數組轉換
1 數組轉集合-基本類型
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
public class Main {
public static void main(String[] args) {
int[] arr = new int[10];
for(int i = 0; i < 10; i++){
arr[i] = i;
}
//1 直接轉
List<Integer> list = new ArrayList<>();
for(int item:arr){
list.add(item);
}
System.out.println(list);
//2 使用 lambda 表達式
list.clear();
list = Arrays.stream(arr).boxed().collect(Collectors.toList());;
System.out.println(list);
}
}
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
運作結果:
🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍
🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍
2 數組轉集合-引用類型
如果需要的集合不可變,直接使用 Arrays.asList(arr) 即可;
如果需要的集合可變,則需要通過 new 關鍵字建立新的集合
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
public class Main {
public static void main(String[] args) {
String[] strs = new String[]{"a","b","c"};
List<String> listStrs = new ArrayList<>(Arrays.asList(strs));
System.out.println(listStrs);
}
}
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
運作結果:
🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍
🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍
3 集合轉數組-轉為 Object 數組
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
public class Main {
public static void main(String[] args) {
String[] strs = new String[]{"a","b","c"};
List<String> listStrs = new ArrayList<>(Arrays.asList(strs));
Object[] objTransfer = listStrs.toArray();
System.out.println(Arrays.toString(objTransfer));
}
}
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
運作結果:
🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍
🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍
4 集合轉數組-指定類型
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
import java.util.*;
public class Main {
public static void main(String[] args) {
String[] strs = new String[]{"a","b","c"};
List<String> listStrs = new ArrayList<>(Arrays.asList(strs));
//指定類型數組,長度不足,按照給定類型建立新數組
String[] transferStrArr1 = listStrs.toArray(new String[0]);
System.out.println(Arrays.toString(transferStrArr1));
//指定類型數組,長度足夠,拷貝到給定類型數組
String[] transferStrArr2 = listStrs.toArray(new String[10]);
System.out.println(Arrays.toString(transferStrArr2));
}
}
❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤
運作結果:
🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍
🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍
驗證一下,看看源碼:
長度不足内部建立了新對象,再進行拷貝
長度足夠的情況直接進行拷貝 System.arrayCopy 操作不會建立新的數組,幾個參數分别是
對于A複制到B的情況,沒有建立新的數組
src對應 A
srcPos 對應從 A 的哪個索引開始複制
dest對應 B
destPos 對應于從 B 的那個索引開始粘貼
Length 就是複制長度
舉個小例子,A=[1,2,3,4,5] B=[6,7,8,9,10] src=A,srcPos=1,dest=B,destPos=2,length=3
相當于 A 複制到 B, 從索引1 開始複制3個,也就是複制 [2,3,4]
B 的粘貼位置是 從 2 開始粘貼長度是3個,也就是 [8,9,10] 會被覆寫
最終 B 數組為 [6,7,2,3,4]
小總結:
📌指定類型數組長度不足,建立新數組傳回
📌指定類型數組長度足夠,按照給定數組傳回
總結:
📌同步視圖、被檢驗視圖相當于對類的擴充與功能補充
📌集合數組可使用傳統方式循環進行拷貝,也可以使用 new ArrayList<>(List.asList()) 和 list.toArray(Type.class) 的方式使用庫進行拷貝