Java中list、array与set的互转

一、array 转 list

1️⃣直接使用Arrays的asList方法

String[] str = new String[]{"a", "b", "c"};
List list = Arrays.asList(str);

2️⃣for循环方式

String[] str = new String[]{"a", "b", "c"};
List list = new ArrayList<>();
for (int i = 0; i < str.length; i++) {
    list.add(str[i]);
}

二、array 与 Set 的互转

三、list 转 array

public static void main(String[] args) {
    List list = new ArrayList();
    list.add("a");
    list.add("b");
    list.add("c");
    String str[] = (String[]) list.toArray();
    System.out.println(str);
}

编译虽通过,但运行时报Exception in thread “main” java.lang.ClassCastException: [Ljava.lang.Object;。正确的写法如下:

String str[] = new String[list.size()];
for (int i = 0; i < list.size(); i++) {
    str[i] = list.get(i);
}

解释:Java中允许向上和向下转型,但是这个转型是否成功是根据Java虚拟机(JVM)中这个对象的类型来实现的。JVM中保存了每个对象的类型,而数组也是一个对象,数组的类型是[Ljava.lang.Object。把[Ljava.lang.Object转换成[Ljava.lang.String显然是不可能的事情,因为这里是一个向下转型,而虚拟机只保存了这是一个Object的数组,不能保证数组中的元素是String的,所以这个转型不能成功。数组里面的元素只是元素的引用,不是存储的具体元素,所以数组中元素的类型还是保存在Java虚拟机中的。

四、解决

由三,可以把这个问题归纳到下面这个模型:

Object objs[]=new Object[10];
String strs[]=(String[])objs;

这样子和刚才上面运行错误是一样的。如果修改代码如下:

String strs[]=new String[10];
Object objs[]=strs;

这样子就可以了。所以这个问题可以归结为 Java 转型规则的问题。JDK5 中,Java 数组开始支持范型,这样可以保证在集合和 Map 中的数据类型的安全。可是,List 的 toArray() 返回的竟然是 Object [] 让人很迷惑。开发者可以根据范型,直接返回相应的 T[]。查看 JDK 源码,发现 List 转化为 array 有两个方法:
1️⃣public Object[] toArray();
该方法把 List 中的全部元素返回一个相同大小的数组,数组中的所有元素都为 Object 类型。
2️⃣public T[] toArray(T[] a);
该方法把 List 中的全部元素返回一个相同大小的数组,数组中的所有元素都为 T 类型。
List 如此设计是因为 Java 编译器不允许 new 范型数组。也就是说不能这么定义一个数组:T arr=new T[size];。但是却可以用 T[] 来表示数组,而且可以把数组强制转化为 T[]。比如 List 中的public T[] toArray(T[] a)是这么实现的:

public  T[] toArray(T[] a) {
    if (a.length < size){
          a=(T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
System.arraycopy(elementData, 0, a, 0, size);
}else if (a.length > size){
    a[size] = null;
}
    return a;
}

由上,因为不知道这个数组的类型,必须通过反射机制创建这个数组(a.getClass().getComponentType()是取得一个数组元素的类型)。最终,List 转换为 Array 可以这样处理:

ArrayList list=new ArrayList();
String[] str= new String[list.size()];
list.toArray(str);

反过来,如将数组转换为 List 如下:

String[] str = {"a","b","c"};
List list = java.util.Arrays.asList(str);

你可能感兴趣的:(Java中list、array与set的互转)