Java 中 list、array 与 set 的互转

一、array 转 list

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

String[] str = new String[]{"a", "b", "c"};
//Arrays.asList()返回java.util.Arrays$ArrayList,而不是 ArrayList。
List<String> list = Arrays.asList(str);

2️⃣for 循环方式

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

二、list 转 array

public static void main(String[] args) {
    List<String> list = Lists.newArrayList("a", "b", "c");
    String[] strArray = (String[]) list.toArray();
    System.out.println(strArray[2]);
}

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

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

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

三、解决

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

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> 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<String> list=new ArrayList<String>();
list.toArray(new String[list.size()]);

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

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

四、array 与 Set 的互转

public static void main(String[] args) {
    Set<String> set = new HashSet<>();
    set.add("a");
    set.add("b");
    // 将set转为数组
    String[] setToArray = set.toArray(new String[set.size()]);
    System.out.println("array的length:" + setToArray.length);
    // 将数组转为set
    HashSet<String> arrayToSet = new HashSet<>(Arrays.asList(setToArray));
    System.out.println("将数组转换为set的元素个数为:" + arrayToSet.size());

    arrayToSet.clear();
    System.out.println(arrayToSet.size());
    arrayToSet.addAll(Arrays.asList(setToArray));
    System.out.println("将数组转换为set的元素个数为:" + arrayToSet.size());
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JFS_Study

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值