文章目录

  • 一、深入思考
  • (一)避开基本类型数组转换集合陷阱
  • (二)不可忽略的默认初始化
  • (三)数组转换为List集合
  • com.google.common.primitives.Ints
  • java.util.Arrays#asList(T... a)
  • Apache org.apache.commons.lang3.ArrayUtils.toObject
  • Arrays.stream().boxed().collect()
  • (四)数组转换为Set集合
  • 将基本数据类型数组转换为Set集合
  • 将引用类型数组转换为Set集合
  • (五)List集合转换为数组
  • (六)Set集合转换为数组
  • 总结


一、深入思考

(一)避开基本类型数组转换集合陷阱

将已知数组转换为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,内容分别是1234567null
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()仅支持接收intlongdouble基本数据类型数组和引用类型数组
  • 支持对返回的List实现进行增删操作

运用场景:

  • 明确待转换的数组元素类型为intlongdouble基本数据类型或引用类型
/**
 * 利用 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()时,不能传递基本数据类型的数组作为其参数,否则容易出现逻辑错乱的问题。
  • 时刻注意数组会给未赋值的位置进行默认初始化操作。