文章目录
一、深入思考
(一)避开基本类型数组转换集合陷阱
将已知数组转换为List集合,观察以下的案例,集合的元素数量是多少?
- 此时集合的元素数量为1,那其他四个元素到哪里去了?
public static void main(String[] args) {
int[] intArray = new int[]{1, 2, 3, 4};
List list = Arrays.asList(intArray);
System.out.println("集合中的元素数量:" + list.size());
}
我们阅读
java.util.Arrays#asList
的源代码,可以发现asList
方法的入参是泛型的可变参数
,返回的是一个固定大小的List集合,大小取决于数组的空间大小,因为数组会默认初始化,会把未赋值的位置进行默认初始化。需要注意一点是,
基本类型是没有泛型
这一概念的,也就是说基本数据类型是不能够作为泛型参数的,要想成为泛型参数,就得使用其对应的包装类型
。// java.util.Arrays#asList // Returns a fixed-size list backed by the specified array public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }
- 既然基本类型不存在泛型化,那么为什么我们在传入int类型数组的时候,不会出现编译报错呢?
数组是一个对象(在Java的世界里),它是可以实现泛型化的,也就是说,在上面的案例中,我们相当于传递的是一个
T为数组类型
的参数,也因此在转换后List集合中只有一个类型为int数组
的元素。我们也可以推断出,直接将
基本类型数组
作为asList
的参数,List集合存储的是数组的引用
,List集合元素个数为1
public static void main(String[] args) { boolean[] booleanArray = new boolean[]{true, false, false, false}; List<boolean[]> list = Arrays.asList(booleanArray); System.out.println("元素类型:" + list.get(0).getClass()); System.out.println("转换前后是否相等:" + Arrays.equals(booleanArray, list.get(0))); }
元素类型:class [Z 转换前后是否相等:true
public static void main(String[] args) {
Integer[] integerArray = new Integer[]{1, 2, 3, 4};
List<Integer> integerList = Arrays.asList(integerArray);
System.out.println("集合元素个数:" + integerList.size());
for (int i = 0, size = integerList.size(); i < size; i++) {
System.out.println(integerList.get(i));
}
}
集合元素个数:4
1
2
3
4
我们只需要将基本数据类型改为对应的包装类型即可
(二)不可忽略的默认初始化
我们知道
Arrays.asList()
,传递包装类型的数组可以解决基本数据类型数组无法泛型化的问题不过,我们可以再来观察以下的代码案例,看看此时的List集合里面有多少元素,存的都是什么内容
- 此时List集合的元素个数为
3
,内容分别是123
,4567
,null
public static void main(String[] args) {
Integer[] integerArray = new Integer[3];
integerArray[0] = 123;
integerArray[1] = 4567;
List<Integer> integerList = Arrays.asList(integerArray);
System.out.println("集合元素个数:" + integerList.size());
for (int i = 0; i < integerList.size(); i++) {
System.out.println(integerList.get(i));
}
}
集合元素个数:3
123
4567
null
注意!我们在一开始的时候,给数组分配了
3
个位置的空间大小,但只是给其中两个位置赋上了值,而由于数组会存在默认初始化的骚操作,并且该数组是包装类型的,导致剩余的位置被初始化为null
。
(三)数组转换为List集合
com.google.common.primitives.Ints
运用场景:
- 明确
待转换的数组元素类型
为基本数据类型
时,推荐/** * 利用 com.google.common.primitives.Ints 将基本数据类型数组转换为 com.google.common.primitives.Ints.IntArrayAsList * <p> * 说明: * 1. com.google.common.primitives.Ints.asList 不支持对返回的List实现进行增删操作 * 2. 8种基本数据类型都有对应的类进行asList操作,例如Booleans, Bytes, Chars等 * <p> * 运用场景: * 1. 明确待转换的数组元素类型为基本数据类型时,推荐 * * @param array 待转换数组 */ public static void intsProcess(int[] array) { List<Integer> integers = new ArrayList<>(Ints.asList(array)); integers.forEach(System.out::println); }
java.util.Arrays#asList(T… a)
运用场景:
- 明确
待转换的数组元素类型
为引用类型
时,推荐/** * 利用 java.util.Arrays#asList(T... a) * <p> * 说明: * 1. Arrays.asList(T... a) 仅支持引用类型数组,不支持基本数据类型数组,如果传递基本类型数组会出现逻辑错乱问题 * <p> * 运用场景: * 1. 明确待转换的数组元素类型为引用类型时,推荐 */ public static void asListProcess() { Integer[] integerArray = new Integer[]{1, 2, 3}; List<Integer> arrayList = new ArrayList<>(Arrays.asList(integerArray)); arrayList.forEach(System.out::println); }
Apache org.apache.commons.lang3.ArrayUtils.toObject
说明:
- 基本数据类型数组转换为对应的包装类型数组,可以使用
ArrayUtils.toObject
- 包装类型数组转换为基本数据类型数组,可以使用
ArrayUtils.toPrimitive
/** * 利用 Apache org.apache.commons.lang3.ArrayUtils.toObject 可将8种基本数据类型转换为对应的包装类型数组 * <p> * 说明: * 1. 基本数据类型数组转换为对应的包装类型数组,可以使用ArrayUtils.toObject * 2. 包装类型数组转换为基本数据类型数组,可以使用ArrayUtils.toPrimitive * <p> * 运用场景: * 1. 明确待转换的数组元素类型为基本数据类型时 */ public static void arrayUtilsProcess() { boolean[] booleanArray = new boolean[]{true, false, false}; List<Boolean> arrayList = new ArrayList<>(booleanArray.length); Collections.addAll(arrayList, ArrayUtils.toObject(booleanArray)); arrayList.forEach(System.out::println); }
Arrays.stream().boxed().collect()
注意事项说明:
- Arrays.stream()仅支持接收
int
,long
,double
基本数据类型数组和引用类型数组- 支持对返回的List实现进行增删操作
运用场景:
- 明确待转换的数组元素类型为
int
,long
,double
基本数据类型或引用类型/** * 利用 Arrays.stream().boxed().collect() * <p> * 说明: * 1. Arrays.stream()仅支持接收int,long,double基本数据类型数组和引用类型数组 * 2. 支持对返回的List实现进行增删操作 * 3. 当处理自定义对象类型的数组时,不需要再加.boxed()方法 * Arrays.stream(personArray).collect(Collectors.toList()) * <p> * 运用场景: * 1. 明确待转换的数组元素类型为int,long,double基本数据类型或引用类型 * * @param array 待转换数组 */ private static void arrayStreamProcess(int[] array) { List<Integer> list = Arrays.stream(array) .boxed() .collect(Collectors.toList()); list.add(65465); list.remove(1); list.forEach(System.out::println); }
1 3 65465
(四)数组转换为Set集合
将基本数据类型数组转换为Set集合
/** * 将基本数据类型数组转换为Set集合 * * @param array 待转换的基本数据类型数组 */ public static void setsProcessPrimitive(int[] array) { Set<Integer> integerHashSet = new HashSet<>(Ints.asList(array)); integerHashSet.add(89846513); integerHashSet.forEach(System.out::println); }
将引用类型数组转换为Set集合
/** * 将引用类型数组转换为Set集合 * * @param array 待转换的引用类型数组 */ public static void setsProcessObject(Student[] array) { Set<Student> hashSet = new HashSet<>(Arrays.asList(array)); hashSet.add(new Student("3", 45)); hashSet.forEach(System.out::println); }
(五)List集合转换为数组
public static void main(String[] args) {
Student student = new Student("1", 0);
Student student1 = new Student("2", 0);
List<Student> studentArrayList = new ArrayList<>();
studentArrayList.add(student);
studentArrayList.add(student1);
toArrayProcessBySize(studentArrayList);
toArrayProcess(studentArrayList);
}
/**
* @param list 待转换的List集合
*/
public static void toArrayProcessBySize(List<Student> list) {
Student[] resultArray = new Student[list.size()];
resultArray = list.toArray(resultArray);
System.out.println(Arrays.toString(resultArray));
}
/**
* @param list 待转换的List集合
*/
public static void toArrayProcess(List<Student> list) {
Student[] studentArray = list.toArray(new Student[0]);
System.out.println(Arrays.toString(studentArray));
}
(六)Set集合转换为数组
public static void main(String[] args) {
Student student = new Student("1", 0);
Student student1 = new Student("2", 0);
Set<Student> studentHashSet = new HashSet<>();
studentHashSet.add(student);
studentHashSet.add(student1);
toArrayProcessBySize(studentHashSet);
toArrayProcess(studentHashSet);
}
/**
* @param set 待转换的Set集合
*/
private static void toArrayProcessBySize(Set<Student> set) {
Student[] resultArray = new Student[set.size()];
resultArray = set.toArray(resultArray);
System.out.println(Arrays.toString(resultArray));
}
/**
* @param set 待转换的Set集合
*/
private static void toArrayProcess(Set<Student> set) {
Student[] studentArray = set.toArray(new Student[0]);
System.out.println(Arrays.toString(studentArray));
}
总结
- 当使用Arrays.asList()时,不能传递基本数据类型的数组作为其参数,否则容易出现逻辑错乱的问题。
- 时刻注意数组会给未赋值的位置进行默认初始化操作。