首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

大家来评论下ArrayList中的subList的设计解决办法

2012-02-13 
大家来评论下ArrayList中的subList的设计如下代码Java codeList l new ArrayList()l.add(a)l.add(b

大家来评论下ArrayList中的subList的设计
如下代码

Java code
    List l = new ArrayList();    l.add("a");    l.add("b");    l.add("c");    List s = l.subList(0, 2);    l.remove(0);    l.add("d");    System.out.println(s.size());

将会抛出java.util.ConcurrentModificationException
看了下源码,发现subList只是复制了引用,并且新生产的subList也是一个ArrayList实例
这样子的话,如果一个ArrayList调用了subList之后,岂不是代表不能再对两个中的任一个list进行修改(即调用add或remove方法)了,原因如下:
假设一个ArrayList A 调用了subList之后生成一个B,由于A,B都是ArrayList实例,并且A和B都是“快速失败”的,而且A和B共用了一块部分,如果此时修改A,B将会抛ConcurrentModificationException,同理修改B,A也会抛异常。
不知道我的理解对不对,如果没理解错的话,这种设计岂不是很糟糕。以后岂不是调用subList要很小心了。

[解决办法]
这是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>

测试:
Java code
 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());
[解决办法]
API的中文说明:

返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。(如果 fromIndex 和 toIndex 相等,则返回的列表为空)。返回的列表由此列表支持,因此返回列表中的非结构性更改将反映在此列表中,反之亦然。返回的列表支持此列表支持的所有可选列表操作。
此方法省去了显式范围操作(此操作通常针对数组存在)。通过传递 subList 视图而非整个列表,期望列表的任何操作可用作范围操作。例如,下面的语句从列表中移除了元素的范围: 

list.subList(from, to).clear();
 可以对 indexOf 和 lastIndexOf 构造类似的语句,而且 Collections 类中的所有算法都可以应用于 subList。
如果支持列表(即此列表)通过任何其他方式(而不是通过返回的列表)从结构上修改,则此方法返回的列表语义将变为未定义(从结构上修改是指更改列表的大小,或者以其他方式打乱列表,使正在进行的迭代产生错误的结果)。 

所以可以像2楼那样用s进行添加或者删除操作。
[解决办法]
探讨

引用:

The returned list is backed by this list, so non-structural
changes in the returned list are reflected in this list, and vice-versa.

如果把你的代码s.add("d");改成l.add("d");就会抛Concur……

[解决办法]
既然你是为了高效便捷而去引用subList,那必然在灵活性上要有所牺牲。

如果你强调灵活性,那不如直接复制出来,就可以随便玩了,但必然效率和空间要做微量牺牲。

说到底都是权衡选择的问题。

热点排行