
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) 的方式使用库进行拷贝