博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Arrays.asList()方法
阅读量:5238 次
发布时间:2019-06-14

本文共 3807 字,大约阅读时间需要 12 分钟。

原文地址:

本文是对Arrays.asList()方法从源码角度进行分析,解析使用中的一些困惑。

首先看Arrays.asList()的源码

public static 
List
asList(T... a) {   return new ArrayList
(a); }

使用该方法可以将一个变长参数或者数组转换成List

看似很简单但实际使用起来却会发现存在很多问题,看下面代码来发现问题。

问题一:基本类型数组作为参数问题

public class ArraysAsListTest {  public static void main(String[] args) {    int[] a = {1,2,3};    Integer[] b = {1,2,3};    List listA = Arrays.asList(a);    List listA1 = Arrays.asList(1,2,3);    List listB = Arrays.asList(b);    System.out.println(listA.size());//out:1    System.out.println(listA1.size());//out:3    System.out.println(listB.size());//out:3  }}

嗯?用int类型的数组作为参数为什么输出size是1呢,使用Integer类型size就是3了呢。

再看源码,asList接收的是一个泛型变长参数,而我们知道基本类型是不能泛型化的,就是说8种基本类型不能作为泛型参数,要想作为泛型参数就要使用其所对应的包装类。

但是listA的Size为什么是1呢,这是因为listA传递的是一个int类型的数组,数组是一个对象,它是可以泛型化的,也就是说例子中是把一个int类型的数组作为了T的类型,所以转换后在List中就只有一个类型为int数组的元素。后边ListA1与ListB也就可以理解了,一个是进行了自动打包,一个是本来就是包装类型。

我们可以打印下list中元素类型进行验证

System.out.println("ListA元素类型:"+listA.get(0).getClass());//out:ListA元素类型:class [ISystem.out.println("ListA元素:"+Arrays.toString((int[]) listA.get(0)));//ListA元素:[1, 2, 3] 该处是为了验证list中元素System.out.println("ListA1元素类型:"+listA1.get(0).getClass());//out:ListA1元素类型:class java.lang.IntegerSystem.out.println("ListB元素类型:"+listB.get(0).getClass());//out:ListB元素类型:class java.lang.Integer

问题二:asList()方法返回对象使用add()方法抛出异常

public class ArraysAsListTest {    public static void main(String[] args) {    List
pets = Arrays.asList("cat","dog"); pets.add("what"); }}异常:Exception in thread "main" java.lang.UnsupportedOperationExceptionat java.util.AbstractList.add(Unknown Source)at java.util.AbstractList.add(Unknown Source)at ArraysAsListTest.main(ArraysAsListTest.java:9)

What?一个List执行add方法会抛出异常,难道add方法不是List的基本用法吗。还是来研究下asList的实现吧

查看一下Arrays.asList中使用的ArrayList到底长啥样?

原来Arrays的asList方法使用的ArrayList类是一个内部定义的类,而不是java.util.ArrayList类。看其部分源码

public class Arrays { ....... private static class ArrayList
extends AbstractList
implements RandomAccess, java.io.Serializable { private static final long serialVersionUID = -2764017481108945198L; private final E[] a; ArrayList(E[] array) { if (array==null) throw new NullPointerException(); a = array; } ...... } }

这个静态内部类,存储数组元素的a变量是final类型的,由此判断,这个静态内部类是不能做任何内部元素的添加删除操作的!就跟String类一样,String对象存储字符数组的变量也是有final修饰符的。因为一旦增加数组元素,这个数组容量已经定好的容器就无法装载增加的元素了。

内部类里面并没有add,remove方法,可以看下这个类继承的AbstractList类里面对这些方法的实现

public abstract class AbstractList
extends AbstractCollection
implements List
{ ........ public void add(int index, E element) { throw new UnsupportedOperationException(); } public E remove(int index) { throw new UnsupportedOperationException(); } }

Ok!找到异常的来源了,我们使用asList得到的对象add、remove方法直接就是抛出异常

如果要对asList得到的对象使用add、remove方法可以使用如下解决办法

List
pets = new ArrayList
(Arrays.asList("a", "b", "c"));

问题三:上代码

public class ArraysAsListTest {  public static void main(String[] args) {
    String[] test = {"a","b","c","d","e"};    List
testList = Arrays.asList(test);    System.out.println("list原始顺序:"+testList);    //洗牌打乱list中元素顺序 使用Collections.shuffled方法    Collections.shuffle(testList, new Random(2));    System.out.println("list打乱后顺序:"+testList);    //list顺序打乱后 原数组会发生神马???    System.out.println("list打乱顺序后数组内容:"+Arrays.toString(test));    /*    * list原始顺序:[a, b, c, d, e]    list打乱后顺序:[e, a, c, b, d]    list打乱顺序后数组内容:[e, a, c, b, d]    */  }}

哦,NO!!!我只是改变list的顺序,然而数组顺序却也发生了变化,很多时候这并不是我们想要的。

这时候我们就要意识到Arrays.asList()产生的list对象会使用底层数组作为其物理实现,只要执行操作修改这个list就会修改原来的数组。要想不改变原来数组,就要在另一个容器中创建一个副本,写法如下

List
testList = new ArrayList
(Arrays.asList(test));

 

转载于:https://www.cnblogs.com/daijiabao/p/11224918.html

你可能感兴趣的文章
Atlas命名空间Sys.Data下控件介绍——DataColumn,DataRow和DataTable
查看>>
Java中正则表达式的使用
查看>>
算法之搜索篇
查看>>
新的开始
查看>>
java Facade模式
查看>>
NYOJ 120校园网络(有向图的强连通分量)(Kosaraju算法)
查看>>
Leetcode 226: Invert Binary Tree
查看>>
http站点转https站点教程
查看>>
解决miner.start() 返回null
查看>>
bzoj 2007: [Noi2010]海拔【最小割+dijskstra】
查看>>
BZOJ 1001--[BeiJing2006]狼抓兔子(最短路&对偶图)
查看>>
C# Dynamic通用反序列化Json类型并遍历属性比较
查看>>
128 Longest Consecutive Sequence 一个无序整数数组中找到最长连续序列
查看>>
定制jackson的自定义序列化(null值的处理)
查看>>
auth模块
查看>>
javascript keycode大全
查看>>
前台freemark获取后台的值
查看>>
log4j.properties的作用
查看>>
游戏偶感
查看>>
Leetcode: Unique Binary Search Trees II
查看>>