java list 转数组_数组转List,一定要小心这个坑!
关注“Java技术迷”升职加薪不脱发!
在日常开发过程中,数组转List的使用频率非常之高。大家可以回想一下,通常你都是怎么转的呢?
用代码说话,下面来看一段代码:
public class Test { public static void main(String[] args) { List list= Arrays.asList("hello","world"); System.out.println(list.remove("hello")); }}
先自己想想这段代码有没有问题,使用
List list= Arrays.asList("hello","world");
来创建一个List,然后再使用remove将其移除。从逻辑上来说,确实没毛病,也有很多人认为这本来就没问题。下面我们来运行一下上面这段代码,结果:
很多人估计都不敢相信自己的眼睛,上面这段代码居然会报错。
如果我们把上面这段代码改一下:
public class Test { public static void main(String[] args) { List list= new ArrayList<>(); list.add("hello"); list.add("world"); System.out.println(list.remove("hello")); }}
运行结果:
true
奇了怪了吧,这就没问题了。
我们来看看
Arrays.asList("hello");
这个asList方法到底干了些什么?
public static List asList(T... a) {return new ArrayList<>(a);}
粗略的看了一下,他返回的不就是ArrayList
对象吗?下面这段代码也是new一个ArrayList对象。
List list= new ArrayList<>();
为什么上面那段就不行呢?整个java.util.Arrays.ArrayList
类有哪些方法
他居然是Arrays的一个静态内部类。现在可以确认这个
java.util.Arrays.ArrayList
和java.util.ArrayList
不是同一个。
重点来了,这个静态内部类里有个final修饰的数组:
private final E[] a;
final修饰变量表示此变量是不可修改的。也就是我们上面的remove为什么报错的原因。居然是因为这个Arrays中的ArrayList中使用的是一个固定大小的数据来存储数据的,同理我们也可以推断,不能使用add方法,下面我来试试add方法就知道了。
public class Test { public static void main(String[] args) { List list= Arrays.asList("hello","world"); System.out.println(list.add("!")); }}
运行结果:
运行结果和我们预期的是一样的。
另外我们看看java.util.ArrayList
源码:
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { private static final long serialVersionUID = 8683452581122892189L;
/** * Default initial capacity. */ private static final int DEFAULT_CAPACITY = 10; private static final Object[] EMPTY_ELEMENTDATA = {}; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; transient Object[] elementData;
这段代码有也有个数组用来保存数据:
transient Object[] elementData;
人家不是使用final修饰,transient
修饰只是和系列化有关系。所以人家java.util.ArrayList
是不会报异常的。
上面Arrays.ArrayList中居然没有add和remove方法。认真的你会发现,它也继承了AbstractList。进去看看她的源码:
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
protected AbstractList() { }
//这是前面我们使用过,并且抛异常的方法 public boolean add(E e) { add(size(), e); return true; } //上面的add方法调用的是这个方法 public void add(int index, E element) { //抛异常 throw new UnsupportedOperationException(); }
public E remove(int index) { //抛异常 throw new UnsupportedOperationException(); } //其他代码省略
}
前面已经把java.util.Arrays.ArrayList
的方法都看过了,并没有add和remove,也就是说他没实现父类的add和remove两个方法。那就是调用了AbstractList
的方法了,所以上面抛的两个异常是在这里抛出来的。
相反java.util.ArrayList
却老老实实的两个方法都实现了。
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } public E remove(int index) { rangeCheck(index);
modCount++; E oldValue = elementData(index);
int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // clear to let GC do its work
return oldValue; }
好了,上面问题已经得出了答案。下面来说说应该如何正确使用数组转List。
正确的姿势
倒也不是说List list= Arrays.asList("hello");
这个不要用,只是你得搞清楚原理,一不小心就会为别人(也可能是自己)留下坑。
方式一:
String[] strings = {"hello", "world"};List list = new ArrayList(Arrays.asList(strings));
方式二(推荐):
String[] strings = {"hello", "world"}; List list = new ArrayList<>(strings.length); Collections.addAll(list, strings);
方式三:
原始的方法就是变量数组,然后new 对象ArrayList,遍历数组,一个一个add进去,这里就不贴代码了,这是最笨的办法。
总结
Arrays.asList(strArray)方式将数组转换为List后,不能增删改原数组的值,仅作读取使用;
ArrayList构造器方式,在List的数据量不大的情况下,可以使用;
集合工具类Collections.addAll(),在List的数据量巨大的情况下,优先使用,可以提高操作速度。
不仅是ArrayList,其余List的子类(LinkList/Vector)也可以用同样的方法实现数组和集合转变。
推荐阅读 点击标题可跳转IDEA 上位?不!Eclipse Theia 1.0 发布!Fastjson到了说再见的时候了JDK15正式发布,划时代的ZGC同时宣布转正看完本文有收获?请转发分享给更多人
关注「Java技术迷」,提升Java技能
java list 转数组_数组转List,一定要小心这个坑!相关推荐
- arrays中copyof复制两个数组_数组,及二维数组
1.1 命令行参数(C) 在程序运行过程中,可以向应用程序传递一些参数,这些参数称为命名行参数. public 命令行参数以字符串的形式传入args数组中.可以一次传递0-多个参数,以空格分割. 如果 ...
- 扩容是元素还是数组_数组是如何随机访问元素?数组下标为什么从0开始,而不是1?...
作者:鹏磊 来源:搜云库技术团队 数组如何实现随机访问元素 什么是数组? 数组(Array)是一种线性表数据结构,它用一组连续的内存空间,来存储相同类型的数据. 什么是线性表(Linear List) ...
- c字符串分割成数组_数组与字符串
定义数组时,应该注意以下几点: (1) 数组使用的是方括号[ ],不要误写成小括号( ). (2) 常量表达式的值必须是一个正整数值,不能含有变量,但是可以是符号常数或常量表达式. (3) 数组定义后 ...
- pycharm定义空的二维数组_数组与面向对象
数组与面向对象 数组 一维数组 数组:[ ] 存储相同类型的多个数据 变量:单个数据 数组:多个数据 数组的特点: 引用数据类型 数据是个容器,长度一旦确定不可改变 一个数组中存放的多个数据的类型要求 ...
- java中int边界值_数组中重复的数字2019.12.06
记录一下,记录一下,记录一下,因为我的记忆好像只有10s 题目描述: 在一个长度为n的数组里面,所有元素的范围是[0,n-1],数组中可能存在某些数字是重复的,请判断是否有重复元素,如果有,找出来. ...
- java环形数组_数组实现环形队列Java
用数组实现环形队列的特点是高效. 能快速判断队列是否 满/空: 能快速存取数据. 因为简单高效,所以甚至在硬件中都实现了环形队列. 环形队列广泛应用于网络数据的收发,和不同应用间数据交换(内核和应用程 ...
- java随机数去重排序_数组去重及排序/0~10随机数字/字符串中出现最多的字符及次数...
数组去重及排序: var arr = [1,5,1,2,6,8,1,81,9,0]; for(var i=0;i for(var j=i+1;j if(arr[i] == arr[j]){ arr.s ...
- c#json对象转数组_数组和对象的区别
数组和对象两者都可以用来表示数据的集合,曾一度搞不清楚"数组"(array)和"对象"(object)的根本区别在哪里. 有一个数组a=[1,2,3,4],还有 ...
- 转为字符数组_数组的20种常用的方法?
1.shift 删除数组中的第一个元素 2.pop 删除数组中的最后一个元素 3.unshift 增加元素在数组的前面 4.push 增加元素在数组的后面 5.map 循环,并且返回新的数组 6.fo ...
最新文章
- 学习ui设计的流程是什么
- 互联网人的求生战役!分享身边的 5 个故事
- 通用的异步处理类和进度通知类及其示例
- mybatis处理集合、循环、数组和in等语句的使用
- python中scale_Python中的Log-scale mathplotlib?
- mysql5.7 备份恢复_RDS for MySQL 5.7 备份恢复为本地实例-阿里云开发者社区
- 接口测试基础与工具(一)
- sharp s2 android 9,夏普s2第三方ROM AOSP(Android P)v105
- beyond 注册表删除
- userdel: user user is currently used by process 18752解决办法
- vos3000配置与通讯测试(一)
- 鸿蒙系统诞生的背景,为何国产系统发展多年无人问津,华为鸿蒙系统刚一开始就引起轰动...
- 【统计学习方法】第10章 隐马尔可夫模型
- PROE5.0飞利浦耳机结构设计教程
- SpringBoot+Vue项目实现高校学生健康打卡系统
- 图书管理系统-数据库设计
- 电磁场与仿真软件(18)
- 【27】unet网络复现及学习(1)
- unc0ver更新适用于iOS14的越狱工具
- 32位全彩色与24位全彩色有啥区别