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); 
测试结果为: 
测试结果 
地址图解释: 
地址描述 

也就是说,修改这个子列表,将导致原列表也发生改变;反之亦然。 

下面是一段示例代码: 

  1. import java.util.ArrayList;  
  2. import java.util.List;  
  3.   
  4. public class TestSubList {  
  5.   
  6.     public static void main(String[] args) {  
  7.         List<Integer> test = new ArrayList<Integer>();  
  8.         //init list  
  9.         for (int i = 0; i < 5; i++) {  
  10.             test.add(i);    //auto boxing  
  11.         }  
  12.         //display the list  
  13.         System.out.print("the orginal list: ");  
  14.         for (int i = 0; i < test.size(); i++) {  
  15.             System.out.print(test.get(i) + " ");  
  16.         }  
  17.         System.out.println();  
  18.           
  19.         //sub list  
  20.         List<Integer> sub = test.subList(13);       //sub list contains elements: 1, 2  
  21.         sub.remove(1);      //remove element “2” from sub list  
  22.           
  23.         //display the list again  
  24.         System.out.print("the orginal list after sublist modified: ");  
  25.         for (int i = 0; i < test.size(); i++) {  
  26.             System.out.print(test.get(i) + " ");  
  27.         }  
  28.         System.out.println();  
  29.     }  
  30.   
  31. }  


程序运行结果: 

    the orginal list: 0 1 2 3 4 
    the orginal list after sublist modified: 0 1 3 4 

在这段代码中,我们并没有改变原始列表“test”其中的元素。然而,当删除由subList方法得到的子列表中的元素时,原始列表中的该元素也被删除了。

-----》这就说明了一个问题,以后慎用sublist。

猜你喜欢

转载自blog.csdn.net/xsm666/article/details/79894586