Java 集合细节(二):asList 的缺陷
在实际开发过程中我们经常使用 asList 讲数组转换为 List,这个方法使用起来非常方便,但是 asList 方法存在几个缺陷:
一、避免使用基本数据类型数组转换为列表
使用 8 个基本类型数组转换为列表时会存在一个比较有味的缺陷。先看如下程序:
public static void main(String[] args) {
int[] ints = {1,2,3,4,5};
List list = Arrays.asList(ints);
System.out.println("list'size:" + list.size());
}
------------------------------------
outPut:
list'size:1
程序的运行结果并没有像我们预期的那样是 5 而是逆天的 1,这是什么情况?先看源码:
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
asList 接受的参数是一个泛型的变长参数,我们知道基本数据类型是无法发型化的,也就是说 8 个基本类型是无法作为 asList 的参数的, 要想作为泛型参数就必须使用其所对应的包装类型。但是这个这个实例中为什么没有出错呢?因为该实例是将 int 类型的数组当做其参数,而在 Java 中数组是一个对象,它是可以泛型化的。所以该例子是不会产生错误的。既然例子是将整个 int 类型的数组当做泛型参数,那么经过 asList 转换就只有一个 int 的列表了。如下:
public static void main(String[] args) {
int[] ints = {1,2,3,4,5};
List list = Arrays.asList(ints);
System.out.println("list 的类型:" + list.get(0).getClass());
System.out.println("list.get(0) == ints:" + list.get(0).equals(ints));
}
--------------------------------------------
outPut:
list 的类型:class [I
list.get(0) == ints:true
从这个运行结果我们可以充分证明 list 里面的元素就是 int 数组。弄清楚这点了,那么修改方法也就一目了然了:将 int 改变为 Integer。
public static void main(String[] args) {
Integer[] ints = {1,2,3,4,5};
List list = Arrays.asList(ints);
System.out.println("list'size:" + list.size());
System.out.println("list.get(0) 的类型:" + list.get(0).getClass());
System.out.println("list.get(0) == ints[0]:" + list.get(0).equals(ints[0]));
}
----------------------------------------
outPut:
list'size:5
list.get(0) 的类型:class java.lang.Integer
list.get(0) == ints[0]:true
Java 细节(2.1):在使用 asList 时不要将基本数据类型当做参数。
二、asList 产生的列表不可操作
对于上面的实例我们再做一个小小的修改:
public static void main(String[] args) {
Integer[] ints = {1,2,3,4,5};
List list = Arrays.asList(ints);
list.add(6);
}
该实例就是讲 ints 通过 asList 转换为 list 类别,然后再通过 add 方法加一个元素,这个实例简单的不能再简单了,但是运行结果呢?打出我们所料:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(Unknown Source)
at java.util.AbstractList.add(Unknown Source)
at com.chenssy.test.arrayList.AsListTest.main(AsListTest.java:10)
运行结果尽然抛出 UnsupportedOperationException 异常,该异常表示 list 不支持 add 方法。这就让我们郁闷了,list 怎么可能不支持 add 方法呢?难道 JDK 脑袋堵塞了?我们再看 asList 的源码:
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
asList 接受参数后,直接 new 一个 ArrayList,到这里看应该是没有错误的啊?别急,再往下看:
private static class ArrayList<E> extends AbstractList<E>
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;
}
//.................
}
这是 ArrayList 的源码,从这里我们可以看出,此 ArrayList 不是 java.util.ArrayList,他是 Arrays 的内部类。该内部类提供了 size、toArray、get、set、indexOf、contains 方法,而像 add、remove 等改变 list 结果的方法从 AbstractList 父类继承过来,同时这些方法也比较奇葩,它直接抛出 UnsupportedOperationException 异常:
public boolean add(E e) {
add(size(), e);
return true;
}
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
通过这些代码可以看出 asList 返回的列表只不过是一个披着 list 的外衣,它并没有 list 的基本特性(变长)。该 list 是一个长度不可变的列表,传入参数的数组有多长,其返回的列表就只能是多长。所以:
from: http://wiki.jikexueyuan.com/project/java-enhancement/java-thirtysix.html
Java 集合细节(二):asList 的缺陷的更多相关文章
- Java提高篇(三五)-----Java集合细节(一):请为集合指定初始容量
集合是我们在Java编程中使用非常广泛的,它就像大海,海纳百川,像万能容器,盛装万物,而且这个大海,万能容器还可以无限变大(如果条件允许).当这个海.容器的量变得非常大的时候,它的初始容量就会显得很重 ...
- (Set, Map, Collections工具类)JAVA集合框架二
Java集合框架部分细节总结二 Set 实现类:HashSet,TreeSet HashSet 基于HashCode计算元素存放位置,当计算得出哈希码相同时,会调用equals判断是否相同,相同则拒绝 ...
- 【由浅入深理解java集合】(二)——集合 Set
上一篇文章介绍了Set集合的通用知识.Set集合中包含了三个比较重要的实现类:HashSet.TreeSet和EnumSet.本篇文章将重点介绍这三个类. 一.HashSet类 HashSet简介 H ...
- java 集合框架(二)Iterable接口
Iterable接口是java 集合框架的顶级接口,实现此接口使集合对象可以通过迭代器遍历自身元素,我们可以看下它的成员方法 修饰符和返回值 方法名 描述 Iterator<T> iter ...
- Java集合系列(二):ArrayList、LinkedList、Vector的使用方法及区别
本篇博客主要讲解List接口的三个实现类ArrayList.LinkedList.Vector的使用方法以及三者之间的区别. 1. ArrayList使用 ArrayList是List接口最常用的实现 ...
- Java提高篇(三六)-----Java集合细节(二):asList的缺陷
在实际开发过程中我们经常使用asList讲数组转换为List,这个方法使用起来非常方便,但是asList方法存在几个缺陷: 一.避免使用基本数据类型数组转换为列表 使用8个基本类型数组转换为列表时会存 ...
- Java提高配(三七)-----Java集合细节(三):subList的缺陷
我们经常使用subString方法来对String对象进行分割处理,同时我们也可以使用subList.subMap.subSet来对List.Map.Set进行分割处理,但是这个分割存在某些瑕疵. 一 ...
- [知识整理]Java集合(二) - Set
一.实现Set的几个类 HashSet.LinkedHashSet.TreeSet.ConcurrentSkipListSet.CopyOnWriterArraySet 二.对应底层的数据结构 Has ...
- Java提高篇(三八)-----Java集合细节(四):保持compareTo和equals同步
在Java中我们常使用Comparable接口来实现排序,其中compareTo是实现该接口方法.我们知道compareTo返回0表示两个对象相等,返回正数表示大于,返回负数表示小于.同时我们也知道e ...
随机推荐
- Vue常用模板语法
常用模板语法 本篇将在上一篇的基础上记录文本渲染.表达式.过滤器以及常用指令的简单用法. 一.文本渲染 Vue支持动态渲染文本,即在修改属性的同时,实时渲染文本内容.同时为了提高渲染效率,也支持只 ...
- H5中canvas标签制作在线画板
1.介绍 左键点击下移动开始画图.放开鼠标不在画图. 2.重要使用理论 query的使用: 鼠标的按下mousedown 鼠标的移动mousemove 鼠标的放开 mouseup 3.程序 <! ...
- win10无线网连接 提示无法连接到此网络
一.Win10无法连接此网络是怎么回事 对于大多数遇到无法连接此网络问题的,主要是Win10笔记本电脑用户,使用的是无线网络.而出现Win10连接其他无线网络正常,但是就是某个无线网络无法正常连接的时 ...
- Windows下安装Tensorflow(python3.6):记录过程
安装前的情况: 之前使用的都是python2.7,但是tensorflow不支持2.x版本,那只有基于在3.x版本进行安装了 前段时间,我安装VS2017的时候安装了python3.6于是想在此基础上 ...
- mybatis3中@SelectProvider的使用技巧
mybatis的原身是ibatis,现在已经脱离了apache基金会,新官网是http://www.mybatis.org/. mybatis3中增加了使用注解来配置Mapper的新特性,本篇文章主要 ...
- css样式大全整理
字体属性:(font) 大小 {font-size: x-large;}(特大) xx-small;(极小) 一般中文用不到,只要用数值就可以,单位:PX.PD 样式 {font-style: obl ...
- netbeans启动后一会崩溃处理
由于netbeans 默认不支持amd cpu渲染,故需要修改默认配置文件,修改后netbeans没有问题. http://stackoverflow.com/questions/34560485/n ...
- Codeforces.959E.Mahmoud and Ehab and the xor-MST(思路)
题目链接 \(Description\) 有一张\(n\)个点的完全图,从\(0\)到\(n-1\)标号,每两点\(i,j\)间的边权为\(i\oplus j\).求其最小生成树边权之和. \(Sol ...
- 【转载】CMenu自绘---钩子---去除边框
使用默认的CMenu菜单类或者继承CMenu实现的菜单扩展类,在显示的时候最外层都会有边框出现,或者说是具有3D外观(菜单阴影不算),当改变菜单背景色或者需要加个边框线时就会看上去很不美观.看过很多菜 ...
- SVN提示https证书验证失败问题svn: E230001: Server SSL certificate verification failed:
最近在使用Idea 检出 svn项目时,出现了如下的画面 显示需要授权证书,需要证书路径 搜索网上的解决方式:无非以下几种 1.File->Settings->Version Contro ...