javaAPI深入理解(1)如何截断一个List以及List.subList()方法的坑
2017-11-29 18:01
3543 查看
removeRange(int, int);这个方法AbstractList并没有暴露出来,我们应该如何得到一个截短的list?
1 如何得到一个list某个范围的子集sublist
首先想到sublist(int, int)方法 注意此方法参数左闭右开。
测试如下
1.1 修改sublist会影响原来的list
LinkedList<String> ll = new LinkedList<>(); ll.add("a"); ll.add("b"); ll.add("c"); List<String> l2 = ll.subList(1, 2);//[) l2.add("new"); System.out.println(ll); System.out.println(l2);1
2
3
4
5
6
7
8
[a, b, new, c]
[b, new]
可见sublist是快照,sulist插入会影响原list
1.2 修改原list,则sublist的所有操作会报错
LinkedList<String> ll = new LinkedList<>(); ll.add("a"); ll.add("b"); ll.add("c"); List<String> l2 = ll.subList(1, 2);//[) ll.add("d"); System.out.println(ll); System.out.println(l2);1
2
3
4
5
6
7
8
Exception in thread “main” java.util.ConcurrentModificationException
at java.util.SubList.checkForComodification(AbstractList.java:769)
可见如果更改了原来的list,sublist的任何操作都会报错,包括get() size(),listIterator()等所有调用checkForComodification()的地方。
2 如何正确的截断一个List?
subList()返回的是List!是Sublist,而不是原来的类型。
2.1在java.util.AbstractList.subList(int fromIndex, int toIndex)的定义,返回的是java.util.SubList.SubLis:
public List<E> subList(int fromIndex, int toIndex) { return (this instanceof RandomAccess ? new RandomAccessSubList<>(this, fromIndex, toIndex) : new SubList<>(this, fromIndex, toIndex)); } 声明: class SubList<E> extends AbstractList<E>{}1
2
3
4
5
6
7
2.2 LinkedList并没有覆盖这个方法.ArryList自己覆盖了这个方法,返回的是java.util.ArrayList.SubList:
public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, 0, fromIndex, toIndex); } 声明: private class SubList extends AbstractList<E> implements RandomAccess {}1
2
3
4
5
6
看来ArryList处处体现出RandomAccess接口的特性——支持随机访问。
2.3 我们看一下java.util.AbstractList.clear()方法,这正是我们需要的,Sublist的clear就是这个方法
public void clear() { removeRange(0, size()); }1
2
3
2.3.1 ArrayList的覆盖
public void clear() { modCount++; // clear to let GC do its work for (int i = 0; i < size; i++) elementData[i] = null; size = 0; }1
2
3
4
5
6
7
8
9
2.3.2 LinkedList的覆盖
public void clear() { for (Node<E> x = first; x != null; ) { Node<E> next = x.next; x.item = null; x.next = null; x.prev = null; x = next; } first = last = null; size = 0; modCount++; }1
2
3
4
5
6
7
8
9
10
11
12
3 根据1和2
截短一个List的正确姿势:list.subList(from, to).clear();1
总之:
subList是返回一个镜像而不是新示例 用了 得保证原来的list不能更改。
之前的抛异常是因为更改了原来的list而要使用sublist的时候必然报异常。
clear的这个跟这个问题说的是如何获得一个list的某一段顺便释放其他节点。
这个操作后原来的list会截取出来 类型不变。
而subList实际上返回的是java.util.Sublist或者java.util.ArrayList.Sublist。
相关文章推荐
- javaAPI深入理解(1)如何截短一个List以及List.subList()方法的坑
- java进阶之反射:反射基础之如何获取一个类以及如何获取这个类的所有属性和方法(1)
- Java中关于Arrays.asList方法的深入学习与理解
- 深入理解java.lang.Class类以及class类获取实例的三种方法
- 如何开发一个java开源框架-----Jvn框架之实现文件的上传以及方法封装(第六讲)八哥实力讲解
- Java中关于Arrays.asList方法的深入学习与理解
- java进阶之反射:反射基础之如何获取一个类以及如何获取这个类的所有属性和方法(2)
- 【深入理解java集合系列】List,Set,Map用法以及区别
- java api如何获取kafka所有Topic列表,并放置为一个list
- java中的反射机制,以及如何通过反射获取一个类的构造方法 ,成员变量,方法,详细。。
- 用类名做方法的返回值类型 在学习Java的初始阶段,很多同学使用基本数据类型定义变量和引用类型定义变量以及使用类名做方法的返回值类型常常不知所以。今天我以自己的解读方式和个人的理解作一个简单的解释,和
- 源程序List1.java,展示了如何使用list()方法来检查一个目录的内容的实例
- java中如何使用asm动态的生成或修改一个class文件以及asm的架构思想
- java-oop 连接sql数据库的方法和如何调用存储过程以及jdbc事物
- Java方法的重载以及构造函数的理解
- Java中如何循环删除一个集合(如List)中的多个元素
- 判断一个类是否支持某属性和方法以及如何判断IOS的版本
- Java方法的重载以及构造函数的理解
- 【Java】List的subList方法参数误导
- java List.subList方法中的超级大陷阱