SubList
List在开发中是常用的一种数据结构,偶尔也会用到List中的subList方法,这个方法有点意思,一起看下。
01SubList的使用
List接口中有subList(int fromIndex, int toIndex)方法,这个方法返回实现了List接口的SubList的实例,而非当前同类型的实例。Sublist可以简单理解是子List,这个SubList是在AbstractList中定义的,因此只能是包内可见,我们在外面没办法直接访问,先看看SubList的定义。
SubList的定义
首先SubList是继承AbstractList类的,也就实现了List接口,再次这个类没有实现Serializable接口,也就是说,这个类不能序列化。SubList的构造方法中引用原list,对SubList的增删肯定会影响原list的数据。下面就来简单测试一下:
测试用例
实用subList其实很简单,传入两个值,第一个是fromIndex,第二个是toIndex。这两个都是index,但是不包含第二个toIndex的值。
这个例子也验证了对子SubList的添加数据会导致原List的数据变动。
02SubList在使用中常遇到的问题
序列化问题,上面也说了,SubList不能被序列化对子SubList的增删导致原List的数据变化对原List的增删会导致子SubList的的操作抛出并发修改异常不能对SubList强制转型为原类型,比如LinkedList或者ArrayList,会抛出类转换异常下面验证下SubList的并发修改异常
并发修改异常
对原List的添加了一个元素,在操作子SubList的size方法时,抛出了ConcurrentModificationException。为什么为抛出异常呢?
源码中对SubList的增删改查的方法都做了检查,检查原List是否改动过,如果改动了直接抛出异常。根本原因为对原List的增删,会对子list的offset和size造成干扰,导致子SubList的混乱。
对子SubList的修改导致原list的数据变化的问题,我们可以通过重新生成一个List对象来变通实现,代码如下:
List subList = new LinkedList<>(linkedList.subList(0, 2)) ;
03ArrayList中的SubList
ArrayList的subList方法返回的是一个ArrayList的私有内部类SubList的实例,和上面的SubList不是同一个。这个SubList也是继承与AbstractList,但是实现了RandomAccess接口。
ArrayList的subList
请大家注意,这个SubList的使用也有以上问题。
有人可能会问为什么又造了个一个SubList,我个人理解是对数组的操作做了优化,如果你对此有不同见解,请留言讨论。如果以上内容有任何问题请批评指正,谢谢!