Java List Copy,Remove容易出现的问题
主题:List删除元素,复制元素
平台:Window + Eclipse3.3 + JDK6
懒程序员,在代码越写越多的情况下,总想着使用把代码精简一下,能不写if else的,能不写for循环的尽量不想写,但是遇到的问题都要解决的呀,因此调用同逻辑的已存在方法便是首选。
今天就集合类(List)两个容易出错的方法做个记录,可以引以为戒,并且也提供正常的使用方式, 都是在java.utils包,方便使用。
1 package com.longer.list; 2 3 import java.util.ArrayList; 4 import java.util.Arrays; 5 import java.util.Collections; 6 import java.util.Iterator; 7 import java.util.List; 8 9 import junit.framework.TestCase; 10 11 /** 12 * 13 * @author Longer 14 * Apr 23, 2010 2:49:13 PM 15 */ 16 public class ListTest extends TestCase { 17 18 class TempBean{ 19 20 public TempBean( String str ){ 21 this.str = str; 22 } 23 24 String str; 25 26 public String getStr() { 27 return str; 28 } 29 30 public void setStr(String str) { 31 this.str = str; 32 } 33 } 34 35 List<TempBean> tempList = null; 36 protected void setUp() throws Exception { 37 super.setUp(); 38 39 tempList = new ArrayList<TempBean>(); 40 tempList.add( new TempBean("1") ); 41 tempList.add( new TempBean("2") ); 42 tempList.add( new TempBean("30") ); 43 tempList.add( new TempBean("31") ); 44 tempList.add( new TempBean("3") ); 45 } 46 47 protected void tearDown() throws Exception { 48 super.tearDown(); 49 50 tempList.clear(); 51 tempList = null; 52 } 53 54 public void testRemove1(){ 55 56 for (TempBean bean : tempList ) { 57 //exception:java.util.ConcurrentModificationException 58 //tempList.remove( bean ); 59 } 60 System.out.println( tempList ); 61 } 62 63 public void testRemove2(){ 64 65 for (int i = 0; i < tempList.size(); i++) { 66 TempBean bean = tempList.get(i); 67 tempList.remove( i );//or tempList.remove(bean); 68 i--; 69 } 70 System.out.println( tempList ); 71 } 72 73 public void testRemove3(){ 74 75 System.out.println("before remove:" + tempList ); 76 for (Iterator iterator = this.tempList.iterator(); iterator.hasNext();) { 77 iterator.remove(); 78 //exception:java.lang.IllegalStateException 79 //tempList.add( new TempBean("") ); 80 } 81 System.out.println("after remove:"+ tempList ); 82 } 83 84 public void testCopy1(){ 85 86 List<TempBean> newList = new ArrayList<TempBean>(); 87 //exception:java.lang.IndexOutOfBoundsException: Source does not fit in dest 88 //Collections.copy( newList, tempList ); 89 } 90 91 public void testCopy2(){ 92 93 List<TempBean> newList = new ArrayList<TempBean>(Arrays.asList(new TempBean[ this.tempList.size()])); 94 Collections.copy( newList, tempList ); 95 System.out.println( newList ); 96 } 97 }
异常解释:
1:testRemove1-->java.util.ConcurrentModificationException
此类的JavaDOC部分原文:
This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible。
简单翻译:
检测到一个对象存在同步修改,并且此修改不被允许的情况下,此异常将被方法抛出。
因此, 可以看出List是不支持同步修改的,其实整个Collection、Map都与List一样的情况,详细的原因得从迭代器Iterator去研究,这里不做分析。大概理解是Iterator在遍历的时间内,其源对象索引发生了改变,导致了不同步现象。
2)testRemove3-->java.lang.IllegalStateException
此类的JavaDOC部分原文:
Signals that a method has been invoked at an illegal or inappropriate time
简单翻译:
信息灯,一个方法在非法或者不恰当的时间内被调用。
因此, 问题的根源同上。
3)testCopy1-->java.lang.IndexOutOfBoundsException
Collections.copy JavaDOC部分原文:
......The destination list must be at least as long as the source list.......
简单翻译:
目的list必须至少要与源list等长。(目的List可以比源List长度长)
因此, 它这里指的长度是List里的size()方法值,我们都知道new ArrayList()初始化的时候size()等于0,即便是你使用new ArrayList(10)来初始化,也只是预设了一个initialCapacity==10的存储空间,size()还是等于0。因此在使用Collections.copy之前,需要把目的List加一些空的元素,直到目的List的size()值与源List的size()值等长(或更长)。