子列表只是原列表的一个视图
原文参考:《编写高质量代码:改善java程序的151个建议》
本文原创:穆雄雄
上期文章:
上期我们说到,List接口提供了subList方法,其作用是返回一个列表的子列表。并且我们通过案例说明了一个问题,那便是,在原来的list集合基础上,调用subList产生新的List的时候,那么原来的list集合也会随之而改。
在看为什么之前,我们还是先从subList的源码上说起吧。
public List<E> subList(int fromIndex, int toIndex) {
return (this instanceof RandomAccess ?
new RandomAccessSubList<E>(this, fromIndex, toIndex) :
new SubList<E>(this, fromIndex, toIndex));
}
从代码中我们可以看到,instanceof的作用就是查看当前的对象是否是RandomAccess的实例,如果是,则调用RandomAccessSubList方法,否则调用SubList方法,况且进一步查看源码可以得知RandomAccessSubList类也继承至SubList类,所以我们直接来看SubList的源码:
class SubList<E> extends AbstractList<E> {
private final AbstractList<E> l;
private final int offset;
private int size;
SubList(AbstractList<E> list, int fromIndex, int toIndex) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > list.size())
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
l = list;
offset = fromIndex;
size = toIndex - fromIndex;
this.modCount = l.modCount;
}
}
//后面省略其他方法
通过阅读这段代码,我们就很清楚的知道SubList方法的实现原理,它返回的SubList类也是AbstractList的子类,其所有的方法如get、set、add、remove等都是在原始列表上的操作,它自身并没有生成一个数组或是链表,也就是子列表只是原列表的一个视图(View),所有的修改动作都反映在了原列表上。
所以我们表面上操作的是newList,其实操作的还是原来的列表。subList产生的列表只是一个视图,所有的修改动作直接作用于源列表。
往期精彩
点分享
点点赞
点在看