java.util.List接口的方法subList()的说明及使用注意事项
JDK中,List接口有一个实例方法List<E> subList(int fromIndex, int toIndex),其作用是返回一个以fromIndex为起始索引(包含),以toIndex为终止索引(不包含)的子列表(List)。
一、subList简述
原型:List<E> subList(int fromIndex,int toIndex)
1、返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。(如果
fromIndex 和 toIndex
相等,则返回的列表为空)。返回的列表由此列表支持,因此返回列表中的非结构性更改将反映在此列表中,反之亦然。返回的列表支持此列表支持的所有可选列表操作。
2、此方法省去了显式范围操作(此操作通常针对数组存在)。通过传递 subList
视图而非整个列表,期望列表的任何操作可用作范围操作。例如,下面的语句从列表中移除了元素的范围:
list.subList(from, to).clear();
可以对 indexOf 和 lastIndexOf 构造类似的语句,而且 Collections
类中的所有算法都可以应用于 subList。
3、如果支持列表(即此列表)通过任何其他方式(而不是通过返回的列表)从结构上修改,则此方法返回的列表语义将变为未定义(从结构上修改是指更改列表的大小,或者以其他方式打乱列表,使正在进行的迭代产生错误的结果)。
参数:
fromIndex - subList 的低端(包括)
toIndex - subList 的高端(不包括)
返回:
列表中指定范围的视图
抛出:
IndexOutOfBoundsException
- 非法的端点值 (fromIndex < 0 || toIndex > size || fromIndex >
toIndex)
二、解释subList(0,30)
1、这是调用了List中的subList方法,从第0个元素(因为List的序号从0开始)开始,到第30个元素结束,但是不包括第30个元素。返回这样的一个列表,他是原List的一部分。
2、举例,如原来的list中存在0、1、2、3 ... 100共101个数字,则调用list.subList(0,30)后,list变为从0开始,到29结束的数值,不包括30。
三、追寻JDK 源代码
查找java原代码我们可以看到:tempList的subList实现代码在AbstractList类里边,然而无论如何,最终 的结果都是返回一个AbstractList的子类:SubList(该类是一个使用默认修饰符修饰的类,其源代码位于 AbstractList.java类文件里边),
SubList类的构造方法:
SubList(AbstractList 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;
expectedModCount = l.modCount;
}
上面的解释通俗的讲就是,将原来的list赋值给了l,随后将游标移动。所以这两个变量的指向是同一个地址,当我们修改l的值,也就修改了指向的那个地址的值,原来的list值就发生了变化。
我们用一个测试类来测试下:
List list = new ArrayList();
for(int i = 0; i<10 ;i++){
list.add(i);
}
System.out.println(list);
List tempList = list.subList(0, 4);
System.out.println(tempList);
tempList.clear();
for(int i = 1; i<5 ;i++){
tempList.add(i);
}
System.out.println(tempList);
System.out.println(list);
测试结果为:
地址图解释:
也就是说,修改这个子列表,将导致原列表也发生改变;反之亦然。
下面是一段示例代码:
- import java.util.ArrayList;
- import java.util.List;
- public class TestSubList {
- public static void main(String[] args) {
- List<Integer> test = new ArrayList<Integer>();
- //init list
- for (int i = 0; i < 5; i++) {
- test.add(i); //auto boxing
- }
- //display the list
- System.out.print("the orginal list: ");
- for (int i = 0; i < test.size(); i++) {
- System.out.print(test.get(i) + " ");
- }
- System.out.println();
- //sub list
- List<Integer> sub = test.subList(1, 3); //sub list contains elements: 1, 2
- sub.remove(1); //remove element “2” from sub list
- //display the list again
- System.out.print("the orginal list after sublist modified: ");
- for (int i = 0; i < test.size(); i++) {
- System.out.print(test.get(i) + " ");
- }
- System.out.println();
- }
- }
程序运行结果:
the orginal list: 0 1 2 3 4the orginal list after sublist modified: 0 1 3 4
在这段代码中,我们并没有改变原始列表“test”其中的元素。然而,当删除由subList方法得到的子列表中的元素时,原始列表中的该元素也被删除了。
-----》这就说明了一个问题,以后慎用sublist。