目录

1. 泛型方法 + 手动遍历 

2. Arrays.asList() + 列表构造器

3. Arrays.stream() + Stream.collect() 方法

4. Guava 的工具类 (推荐)


1. 泛型方法 + 手动遍历 


JDK1.5 之后才能实现。其原理就是利用泛型方法,使用循环遍历数组,将其手动转为集合。示例代码如下:

/**
 * 第一种数组转列表的方式:
 * JDK1.5+ 泛型方法 + 手动遍历
 *
 * @author wl
 * @date 2022/10/12 11:21
 */
public class ArrayToList01 {

    public static void main(String[] args) {
        // 创建一个 Integer 类型的数组
        Integer [] arr = {16, 41, 89, 33, 40, 54, 48, 37, 35, 44,
                26, 53, 28, 24, 36, 18, 61, 29, 66, 66, };
        List<Integer> manual = manual(arr);
    }

    /**
     * 利用 JDK1.5 之后的泛型特性,
     * 手动将数组转为列表
     *
     * @param array 待转为集合的数组
     * @return java.util.List<T>
     * @author wl
     * @date 2022/10/17 18:17
     */
    public static <T> List<T> manual(final T[] array) {
        // 创建一个泛型列表
        final List<T> list = new ArrayList<>(array.length);
        // 遍历数组,手动将其每个元素加入到刚创建的泛型列表中
        for (final T i : array) {
            list.add(i);
        }
        //
        return list;
    }
}

        不过这个方法仅适用于对象类型的数组,如果是基本数据类型的数组,就比较麻烦,需要为每一种数据类型写一个单独的方法,如下所示:

/**
 * 第一种数组转列表的方式:
 * JDK1.5+ 泛型方法 + 手动遍历
 *
 * @author wl
 * @date 2022/10/12 11:21
 */
public class ArrayToList01 {

    public static void main(String[] args) {
        // 创建一个 Integer 类型的数组
        int [] arr = {16, 41, 89, 33, 40, 54, 48, 37, 35, 44,
                26, 53, 28, 24, 36, 18, 61, 29, 66, 66, };
        // 将数组转为对应类型的列表
        List<Integer> manual = manual(arr);
    }

    /**
     * 将 byte 数组转为 Byte 列表
     *
     * @param array 数组
     * @author wl
     * @date 2022/10/17 19:19
     * @return java.util.List<java.lang.Integer>
     */
    public static List<Byte> manual(byte[] array) {
        // 创建一个泛型列表
        final List<Byte> list = new ArrayList<>(array.length);
        // 遍历数组,手动将其每个元素加入到刚创建的泛型列表中
        for (final byte i : array) {
            list.add(i);
        }
        return list;
    }


    /**
     * 将 short 数组转为 Short 列表
     *
     * @param array 数组
     * @author wl
     * @date 2022/10/17 19:19
     * @return java.util.List<java.lang.Integer>
     */
    public static List<Short> manual(short[] array) {
        // 创建一个泛型列表
        final List<Short> list = new ArrayList<>(array.length);
        // 遍历数组,手动将其每个元素加入到刚创建的泛型列表中
        for (final short i : array) {
            list.add(i);
        }
        return list;
    }

    /**
     * 将 int 数组转为 Integer 列表
     *
     * @param array 数组
     * @author wl
     * @date 2022/10/17 19:19
     * @return java.util.List<java.lang.Integer>
     */
    public static List<Integer> manual(int[] array) {
        // 创建一个泛型列表
        final List<Integer> list = new ArrayList<>(array.length);
        // 遍历数组,手动将其每个元素加入到刚创建的泛型列表中
        for (final int i : array) {
            list.add(i);
        }
        return list;
    }

    /**
     * 将 long 数组转为 Long列表
     *
     * @param array 数组
     * @author wl
     * @date 2022/10/17 19:19
     * @return java.util.List<java.lang.Integer>
     */
    public static List<Long> manual(long[] array) {
        // 创建一个泛型列表
        final List<Long> list = new ArrayList<>(array.length);
        // 遍历数组,手动将其每个元素加入到刚创建的泛型列表中
        for (final long i : array) {
            list.add(i);
        }
        return list;
    }


    /**
     * 将 boolean 数组转为 Boolean 列表
     *
     * @param array 数组
     * @author wl
     * @date 2022/10/17 19:19
     * @return java.util.List<java.lang.Integer>
     */
    public static List<Boolean> manual(boolean[] array) {
        // 创建一个泛型列表
        final List<Boolean> list = new ArrayList<>(array.length);
        // 遍历数组,手动将其每个元素加入到刚创建的泛型列表中
        for (final boolean i : array) {
            list.add(i);
        }
        return list;
    }

    /**
     * 将 float 数组转为 Float 列表
     *
     * @param array 数组
     * @author wl
     * @date 2022/10/17 19:19
     * @return java.util.List<java.lang.Integer>
     */
    public static List<Float> manual(float[] array) {
        // 创建一个泛型列表
        final List<Float> list = new ArrayList<>(array.length);
        // 遍历数组,手动将其每个元素加入到刚创建的泛型列表中
        for (final float i : array) {
            list.add(i);
        }
        return list;
    }

    /**
     * 将 double 数组转为 Double 列表
     *
     * @param array 数组
     * @author wl
     * @date 2022/10/17 19:19
     * @return java.util.List<java.lang.Integer>
     */
    public static List<Double> manual(double[] array) {
        // 创建一个泛型列表
        final List<Double> list = new ArrayList<>(array.length);
        // 遍历数组,手动将其每个元素加入到刚创建的泛型列表中
        for (final double i : array) {
            list.add(i);
        }
        return list;
    }

}

        由于 JDK 官方的 “ 短视 ” ,在早期,也就是 JDK版本还是 1.0 时候的版本没能推出泛型,直到 JDK 1.5 之后才引入了泛型。因为引入的很晚, JDK 官方也考虑到代码可能会有部分兼容性的问题,如果实现真泛型的话,原先的 JDK1.0 的部分代码可能会无法运行。

/**
 * 第一种数组转列表的方式:
 * JDK1.5+ 泛型方法 + 手动遍历
 *
 * @author wl
 * @date 2022/10/18 9:22
 */
public class ArrayToList01 {

    public static void main(String[] args) {
        List<Integer> integerList = new ArrayList<>(20);
        integerList.add(1);
        List<Double> doubleList = new ArrayList<>(20);
        doubleList.add(1.0D);
        Class<? extends Integer> aClass = integerList.get(0).getClass();
        Class<? extends Double> aClass1 = doubleList.get(0).getClass();
        // 这里会打印出 true
        System.out.println(aClass.getClass() == aClass1.getClass());
    }
}

        所以为了保持代码的兼容性,在使用泛型的时候,程序在底层执行  javac 命令编译的时候就会将所有的泛型类型直接替换为 Object 的类型。

2. Arrays.asList() + 列表构造器


        上面那种是手动转置的写法,一般情况不会用到,正常写代码都会直接使用现成的工具类或方法。这是一种常见的写法,相信大家或多或少都见过,不过还是要在这里介绍一下:

/**
 * 第二种数组转列表的方式:
 * Arrays.asList() + 列表构造器
 *
 * @author wl
 * @date 2022/10/12 11:21
 */
public class ArrayToList02 {

    public static void main(String[] args) {
        // 创建数组
        Double[] doubles = new Double[10];
        Scanner in = new Scanner(System.in);
        for (int i = 0; i < doubles.length; i++) {
            doubles[i] = in.nextDouble();
        }
        // 将数组转为对应类型的列表
        List<Double> arrayList = new ArrayList<>(Arrays.asList(doubles));
    }

}

Arrays.asList() 方法其实就可以返回一个列表了,为什么还需要借列表的构造器方法创建列表。其实,原因是这样的,Arrays.asList() 确实会返回一个列表不假,但是这是一个 “ 阉割版 ” 的列表,无法执行增删元素操作,如果强制调用其 add() 或 remove() 方法,就会抛出一个 UnsupportedOperationException  异常,查看底层实现你会发现 Arrays.asList()

        此外,这个方法不适合基本数据类型的数组,必须要先将其转为其包装类的数组才行

3. Arrays.stream() + Stream.collect() 方法


        此方法只适用于 JDK1.8 之后的版本,通过 Stream 流的方法间接把数组转为列表,如果你还不知道如何使用 Stream 流,那么可以看看我的另一篇文章:巧用Stream流

        好了,废话不多说,看看示例吧:

/**
 * 第三种数组转列表的方式:
 * Arrays.stream() + Stream.collect() 方法
 *
 * @author wl
 * @date 2022/10/12 11:21
 */
public class ArrayToList03 {

    public static void main(String[] args) {
        // 创建一个 long 基本数据类型的数组
        Long[] longs = new Long[20];
        for (int i = 0; i < longs.length; i++) {
            longs[i] = (long) (Math.random() * 100L) + 1L;
        }
        // 将数组转为 Stream 流
        Stream<Long> stream = Arrays.stream(longs);
        // 将 Stream 流转为列表
        List<Long> arrayList = stream
                .collect(Collectors.toList());
    }

}

        这种方式也支持部分基本数据类型的数组转为列表,其中包含 int、double 和 long,其他的基本数据类型数组暂不支持:

/**
 * 第三种数组转列表的方式:
 * Arrays.stream() + Stream.collect() 方法
 *
 * @author wl
 * @date 2022/10/12 11:21
 */
public class ArrayToList03 {

    public static void main(String[] args) {
        // 创建 double 类型的数组
        double[] arr = {1.2, 7.4, -4,8, 9.2, 4.0};
        // 通过 Stream 流创建列表
        ArrayList<Object> arrayList = Arrays
                .stream(arr)
                .collect(ArrayList::new, 
                         ArrayList::add, 
                         ArrayList::addAll);
        // 还可以依赖 Boxed 的装箱操作实现
        List<Double> arrayList2 = Arrays.stream(arr)
                .boxed()
                .collect(Collectors.toList());
    }
}

4. Guava 第三方库 (推荐)


在使用前需要先引入依赖或 jar 包:

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
     <groupId>com.google.guava</groupId>
     <artifactId>guava</artifactId>
     <version>23.0</version>
</dependency>

ImmutableList 类及其 of()与 copyOf()

/**
 * 第四种数组转列表的方式:
 * Guava 的工具类 (推荐)
 *
 * @author wl
 * @date 2022/10/12 11:21
 */
public class ArrayToList04 {

    public static void main(String[] args) {
        String[] aStringArray = {"string", "elements"};
        // 对于可变参数使用 ImmutableList 的 of() 方法进行创建
        List<String> i1 = ImmutableList.of("string", "elements");
        // 对于数组则可以使用 ImmutableList 的 copyOf() 方法创建
        List<String> i2 = ImmutableList.copyOf(aStringArray);
    }
}

为什么要使用不可变集合呢,因为不可变集合主要有以下优点:

  • 在多线程操作下,是线程安全的。
  • 所有不可变集合会比可变集合更有效的利用资源
  • 当对象被不可信的库调用时,不可变形式是安全的。
  • 不可变集合不需要考虑变化,因此可以节省时间和空间。
  • 不可变对象因为有固定不变,可以作为常量来安全使用。

        另一种为可变集合,不过在可变集合上,似乎 Guava 不支持用数组创建,因为可变集合的大部分类都是 Map、Set 之类,无法直接或间接支持使用数组进行创建列表,如果想使用可变集合,那么使用 JDK 的 ArrayList 或 LinkedList 就行。