List 接口提供了subList方法,其作用是返回一个原列表的一个视图。对子列表的修改可以直接反馈到原列表中。
/** *subList 只是原列表的一个视图 * @author zhangwei_david * @version $Id: SubListDemo.java, v 0.1 2014年10月18日 下午8:50:33 zhangwei_david Exp $ */ public class SubListDemo { /** * * @param args */ public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("A"); list.add("B"); System.out.println("原列表的内容: " + list); List<String> subList = list.subList(0, list.size()); System.out.println("子列表的内容: " + subList); list = Collections.unmodifiableList(list); subList.add("C"); System.out.println("子列表的内容: " + subList); System.out.println("原列表的内容: " + list); System.out.println("子列表和原列表是否相等:" + subList.equals(list)); } }
原列表的内容: [A, B]
子列表的内容: [A, B]
子列表的内容: [A, B, C]
原列表的内容: [A, B, C]
子列表和原列表是否相等:true
对子列表中的增加可以直接反馈到原列表中。
那么翻过来是否可以呢?我们看下面一个示例:
/** *subList 只是原列表的一个视图 * @author zhangwei_david * @version $Id: SubListDemo.java, v 0.1 2014年10月18日 下午8:50:33 zhangwei_david Exp $ */ public class SubListDemo { /** * * @param args */ public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("A"); list.add("B"); System.out.println("原列表的内容: " + list); List<String> subList = list.subList(0, list.size()); System.out.println("子列表的内容: " + subList); subList.add("C"); System.out.println("子列表的内容: " + subList); System.out.println("原列表的内容: " + list); System.out.println("子列表和原列表是否相等:" + subList.equals(list)); // 修改原列表 list.add("D"); System.out.println("子列表的内容: " + subList); } }
结果是:
子列表的内容: [A, B] 子列表的内容: [A, B, C] 原列表的内容: [A, B, C] 子列表和原列表是否相等:true Exception in thread "main" java.util.ConcurrentModificationException at java.util.SubList.checkForComodification(Unknown Source) at java.util.SubList.listIterator(Unknown Source) at java.util.AbstractList.listIterator(Unknown Source) at java.util.SubList.iterator(Unknown Source) at java.util.AbstractCollection.toString(Unknown Source) at java.lang.String.valueOf(Unknown Source) at java.lang.StringBuilder.append(Unknown Source) at com.cathy.demo.collections.SubListDemo.main(SubListDemo.java:34)
为什么会有并发修改的异常呢?
public List<E> subList(int fromIndex, int toIndex) { return (this instanceof RandomAccess ? new RandomAccessSubList<E>(this, fromIndex, toIndex) : new SubList<E>(this, fromIndex, toIndex)); }
public int size() { checkForComodification(); return size; }
private void checkForComodification() { if (l.modCount != expectedModCount) throw new ConcurrentModificationException(); }
至此我们可以发现在修改原列表后,使用size 方法出现了并发修改异常。
也就是原列表在生成子列表的时候,原列表是不能再被修改的