这是API的解释:  
   * Returns a view of the portion of this list between the specified
     * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.  (If
     * <tt>fromIndex</tt> and <tt>toIndex</tt> are equal, the returned list is
     * empty.)  The returned list is backed by this list, so non-structural
     * changes in the returned list are reflected in this list, and vice-versa.
     * The returned list supports all of the optional list operations      supported
     * by this list.<p>测试:
 List l = new ArrayList();
   l.add("a");
   l.add("b");
    l.add("c");
    List s = l.subList(0, 2);
    s.add("d");
    System.out.println(l.size());
    System.out.println(s.size());

解决方案 »

  1.   

    API的中文说明:返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。(如果 fromIndex 和 toIndex 相等,则返回的列表为空)。返回的列表由此列表支持,因此返回列表中的非结构性更改将反映在此列表中,反之亦然。返回的列表支持此列表支持的所有可选列表操作。
    此方法省去了显式范围操作(此操作通常针对数组存在)。通过传递 subList 视图而非整个列表,期望列表的任何操作可用作范围操作。例如,下面的语句从列表中移除了元素的范围:             list.subList(from, to).clear();
     可以对 indexOf 和 lastIndexOf 构造类似的语句,而且 Collections 类中的所有算法都可以应用于 subList。
    如果支持列表(即此列表)通过任何其他方式(而不是通过返回的列表)从结构上修改,则此方法返回的列表语义将变为未定义(从结构上修改是指更改列表的大小,或者以其他方式打乱列表,使正在进行的迭代产生错误的结果)。 所以可以像2楼那样用s进行添加或者删除操作。
      

  2.   

    如果把你的代码s.add("d");改成l.add("d");就会抛ConcurrentModificationException异常了
      

  3.   

    嗯,是,因为subList()返回的是对原List的“视图”,你所说的引用。
    其实这是实现上的要求,不是设计上的问题,C++的迭代也会有这种问题。因为对集合的修改可能会造成数组所在内存地址的变化。你也可以这样理解:如果两个list都允许修改且做了不同的修改,实际上仅有一个list该怎么应对这种情况呢?
      

  4.   

    既然你是为了高效便捷而去引用subList,那必然在灵活性上要有所牺牲。如果你强调灵活性,那不如直接复制出来,就可以随便玩了,但必然效率和空间要做微量牺牲。说到底都是权衡选择的问题。
      

  5.   

    一语惊醒梦中人啊!!!!
    看了下SbuList类的实现源码,发现是通过组合AbstractList来实现的,这样所有对subList的操作都会转化为对原list的操作。也就说subList和原先的list是共享一块内存空间的。而add/remove操作会引起list的resize等操作从而改变内存地址(比如某块空间不够add了就会new一块新的地址)。由于sublist的初始化是在构造函数中引用原list实现,也就只能初始化一次。这样,当之后对原list进行add/remove操作的话,就可以回导致内存重新分配,而此时,无法重新初始化已经生产的subList,但此时subList指向的内存已经失效。所以,最好的方式就应该是在调用了原list的add/remove方法后再次访问subList时抛出异常。
    感谢cstur4!终于理解了~
      

  6.   

    我也正被这个问题困惑着,现在也大概明白了,还是要去多看源代码和API啊