1. 概述

在使用List集合时有些地方需要注意一下的, 不然会出现一些莫名其妙的错误.

2. Arrays.asList();

2-1. 产生不可操作的集合

来看一个例子.

Integer[] array = {1, 2, 3, 4, 5};
List<Integer> list = Arrays.asList(array);
list.remove(1);

会直接抛出java.lang.UnsupportedOperationException异常, 为什么呢?

答案是: 返回的List非java.util.ArrayList. 而是在Arrays类内部有一个静态内部类叫ArrayList.

静态内部类ArrayList并没有提供所有的方法实现, 有些方法在抽象类中仅仅是一个抛异常的实现, 上述的remove就是这种情况. asList返回的列表只不过是披着list的外衣, 它并没有list的基本特性(变长), 该list是一个长度不可变的列表, 传入参数的数组有多长, 其返回的列表就只能是多长. 所以不要试图改变asList的返回列表.

Arrays.asList的代码如下:

public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
} 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) {
a = Objects.requireNonNull(array);
} // 省略部分源码
}

该类也是继承了AbstractkList抽象类, 只是该类并没有提供所有方法的实现.

2-2. 需要传入对象数组而不是基本类型数组

看个例子:

int[] array1 = {1, 2, 3, 4, 5};
List<int[]> list1 = Arrays.asList(array1);
System.out.println(list1.size()); // 1 Integer[] array2 = {1, 2, 3, 4, 5};
List<Integer> list2 = Arrays.asList(array2);
System.out.println(list2.size()); // 5

看到Array.asList的返回值的泛型就明白, list1中存储的实际是一个数组. 为什么这样呢? 数值类型不能被泛型化, 比如List<int>是不对的, 必须是List<Integer>才对.

3. arrayList.subList();

3-1. subList返回的并不是ArrayList

方法返回的是一个内部类SubList, 并不是ArrayList, SubList也是继承AbstractList, 内部引用了原列表的List.

3-2. subList返回的仅仅是一个视图

subList返回的仅仅是一个视图, 对subList返回值的所有操作都会作用在原列表中.

看一个例子

List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E"); List<String> subList = list.subList(2, 4);
subList.add("F");
System.out.println(list); // 输出 [A, B, C, D, F, E]

通过输出结果可知, F被添加到原列表中了.

3-3. 生成子列表时, 不要试图去操作原列表

因为子列表是根据原列表动态生成的, 所以如果原列表变了, 那么操作子列表时就会发生ConcurrentModificationException异常. 这个异常的原因相信你也知道, 就是modCount改变了导致的.

3-4. 推荐使用subList处理局部链表

比如, 有一个需求要删除列表100-200位置处的数据, 通常我们这样写:

int start = 100;
int end = 200;
for (int i = start; i <= end; i++) {
list.remove(start);
}

通过subList, 我们有一个更简洁的处理方式:

list.subList(100, 200).clear();

简洁.

不定期更新

可能还会遇到集合相关的坑.

随机推荐

  1. iOS 弹幕制作

    离职的最后一天,在公司学习下弹幕的制作.基于OC. 主要思路: 1.首先建一个弹幕类BulletView,基于UIView,然后在该类上写个UIlabel,用于放置弹幕文字,然后前端放置一个UIIma ...

  2. CentOS磁盘满了,导致磁盘无法写入,这么清理

    输入命令 du -sh /* | sort -nr 会列出根目录文件夹的大小 看到哪个文件夹比较大 删除相应的缓存,重启服务器即可

  3. Python全栈之路----函数----参数

    参数可以让你的函数更灵活,不只能做死的动作,还可以根据调用时传参的不同决定函数内部的执行流程. 形参:只有在被调用时才分配内存单元,在调用结束时,即可释放所分配的内存单元.因此形参只在函数内部有效.函 ...

  4. 第四次作业——关于石墨文档(Android)客户端的案例分析

    关于石墨文档(Android)客户端的案例分析 作业地址:[https://edu.cnblogs.com/campus/nenu/2016CS/homework/2505] 第一部分调研,评测 1. ...

  5. C++学习(三十五)(C语言部分)之 单链表

    单链表 就好比火车 火车头-->链表头部火车尾-->链表尾部火车厢-->链表的节点火车厢连接的部分-->指针火车中的内容-->链表节点的的数据链表节点包含数据域和指针域数 ...

  6. EBS获取code_combination_id(CCID)时段值自动被置为默认值的问题

    EBS中在使用标准的API(FND_FLEX_EXT.GET_COMBINATION_ID 和 FND_FLEX_EXT.GET_CCID还有fnd_flex_keyval.validate_segs ...

  7. 【SpringBoot】常用Starter介绍和整合模板引擎Freemaker、thymeleaf

    ========7.SpringBoot常用Starter介绍和整合模板引擎Freemaker.thymeleaf ========================= 1.SpringBoot Sta ...

  8. PythonStudy——python中如何使输出不换行

    1.在python 3.x版本中,使用print(,end="") 可使输出不换行,  例如:

  9. Web前端入门教程之浏览器兼容问题及解决方法

    JavaScript 被称为JS,是作为浏览器的内置脚本语言,为我们提供操控浏览器的能力,可以让网页呈现出各种特殊效果,为用户提供友好的互动体验.JS是Web前端入门教程中的重点和难点,而浏览器兼容性 ...

  10. GradleUserGuide中文版 19)Plugins 20)插件规范 21)Java插件

    https://blog.csdn.net/roymuste/article/details/51321881