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 ...
随机推荐
- Codeforces Round #296 (Div. 1) B - Clique Problem
B - Clique Problem 题目大意:给你坐标轴上n个点,每个点的权值为wi,两个点之间有边当且仅当 |xi - xj| >= wi + wj, 问你两两之间都有边的最大点集的大小. ...
- SpringBoot的Controller使用
一: 1.注解 2.control注解 3.效果 4.RespomseBody package com.caojun.springboot; import org.springframework.be ...
- 使用python爬取整本《盗墓笔记》
一.前言 <盗墓笔记>是一本经典的盗墓题材小说,故事情节引人入胜.本文将使用python2.7通过小说网站http://www.daomubiji.com/来爬取整本盗墓笔记并保存,在这一 ...
- 【转】java取整和java四舍五入方法
java取整和java四舍五入方法 import java.math.BigDecimal; import java.text.DecimalFormat; public class TestGetI ...
- PHP获取访问者公网IP
if(!empty($_SERVER["HTTP_CLIENT_IP"])){ $cip = $_SERVER["HTTP_CLIENT_IP"]; } el ...
- 自然语言处理---用隐马尔科夫模型(HMM)实现词性标注---1998年1月份人民日报语料---learn---test---evaluation---Demo---java实现
先放上一张Demo的测试图 测试的句子及每个分词的词性标注为: 目前/t 这/rzv 条/q 高速公路/n 之间/f 的/ude1 路段/n 已/d 紧急/a 封闭/v ./w 需要基础知识 HM ...
- (3)python tkinter-消息框、对话框、文件对话框
消息框 导入 import tkinter import tkinter.messagebox #这个是消息框,对话框的关键 提示消息框 tkinter.messagebox.showinfo('提示 ...
- [教程] Spring+Mybatis环境配置多数据源
一.简要概述 在做项目的时候遇到需要从两个数据源获取数据,项目使用的Spring + Mybatis环境,看到网上有一些关于多数据源的配置,自己也整理学习一下,然后自动切换实现从不同的数据源获取数据功 ...
- 网站截图工具EyeWitness
网站截图工具EyeWitness 在网页分析和取证中,往往需要大批量的网站截图.Kali Linux提供了一款网站批量截图工具EyeWitness.该工具不仅支持网址列表文件,还支持Nmap和Ne ...
- Linux学习路线+资源
Linux学习路线,个人收集分享 学习路线图 资源链接(蓝色下划线字体对应相应资源链接) Linux 基础 Linux 基础 Linux安装专题教程 Linux中文环境 Linux—从菜鸟到高手 鸟哥 ...