• [改善Java代码]子列表只是原列表的一个视图


    List接口提供了subList方法,其作用是返回一个列表的子列表.这与String类的subString有点类似.但是他们的功能是否相同?看代码:

     1 import java.util.ArrayList;
     2 import java.util.List;
     3 
     4 public class Client {
     5     public static void main(String[] args) {
     6         //定义一个包含两个字符串的列表
     7         List<String> c = new ArrayList<String>();
     8         c.add("A");
     9         c.add("B");    
    10         //构造一个包含c的字符串列表
    11         List<String> c1 = new ArrayList<String>(c);
    12         //通过subList生成与c相同的列表
    13         List<String> c2 = c.subList(0, c.size());
    14         //c2增加一个元素
    15         c2.add("C");        
    16         System.out.println("c == c1? " + c.equals(c1));
    17         System.out.println("c == c2? " + c.equals(c2));
    18         
    19     }
    20 }

    程序输出:

    c == c1? false
    c == c2? true

    c1是通过ArrayList的构造函数创建的,c2是通过列表的subList方法创建的,然后c2又增加了一个元素C,现在的问题是输出的结果是什么呢?

    列表c与c1,c2之间是什么关系呢?

    别忙着回答这个问题,回想一下String类的subString方法,看看它是如何工作的.

    1 public class Client {
    2     public static void main(String[] args) {
    3         String str = "AB";
    4         String str1 = new String(str);
    5         String str2 = str.substring(0) + "C";
    6         System.out.println("str == str1 " + str.equals(str1));
    7         System.out.println("str == str2 " + str.equals(str2));
    8     }
    9 }

    输出结果:

    str == str1 true
    str == str2 false

    很明显str与str1是相等的(虽然不是同一个对象,但用equals方法判断是相等的),但它们与str2不相等,这也毋庸置疑,因为str2在对象池中重新生成了一个新的对象,其值是ABC,那当然与str和str1不相等了.

    为什么subList的结果正好好subString的相反?

    c2是通过subList方法从c列表中生成了 一个子列表,然后c2又增加了一个元素,可为什么增加了 一个元素还会相等呢?看subList的源码:

    1     public List<E> subList(int fromIndex, int toIndex) {
    2         return (this instanceof RandomAccess ?
    3                 new RandomAccessSubList<>(this, fromIndex, toIndex) :
    4                 new SubList<>(this, fromIndex, toIndex));
    5     }

    subList方法由AbstractList实现的,它会根据是不是可以随机存取来提供不同的SubList实现方式,不过,随机存储的使用频率比较高,而且RandomAccessSubList也是SubList子类,所以所有的操作都是由SubList类实现的(除了自身的SubList方法外),

    看SubList的源码:

     

    通过阅读这段代码,就非常清楚的subList方法的实现原理了:它返回的SubList类也是AbstractList的子类,其所有的方法如get,set,add,remove等都是在原始列表上的操作,它自身并没有生成一个数组或是链表,也就是子列表只是原始列表的一个视图(View),所有的修改动作都反映在了原列表上....

    我们例子中的c2增加了一个元素C,不过增加的元素C到了c列表上,两个变量的元素仍然保持完全一致,相等也就很自然了.

    为什么c和c1不相等.因为通过ArrayList构造函数创建的List对象c1实际上是新列表,它是通过数组的copyOf动作生成的,所生成的列表c1与原列表c之间没有任何关系(虽然是浅拷贝,但元素类型是String,也就是说元素是深拷贝的),

    然后c又增加了元素,因为c1与c之间已经没有任何的关系了,自然不相等.

    subList产生的列表只是一个视图,所有的修改动作直接作用于原列表.

  • 相关阅读:
    编写便于打印的Shellcode
    DOS路径转化为NT路径
    当你孤单时你会想起谁
    【转载】从文件句柄获得全路径
    C# DLLImport C++ dll 几点注意事项
    充值系统系统异常处理解决方案
    Demo 与实际应用开发之间的距离
    IIS7.0出错的解决方案 IIS 状态代码:IIS详细错误代码以及解释
    log4net 写日志到 Sql server 数据库
    Log4net 的使用及注意事项
  • 原文地址:https://www.cnblogs.com/DreamDrive/p/5660044.html
Copyright © 2020-2023  润新知