java采坑总结

一、一些特殊集合

1 、把 Array 转换 为 ArrayList
List<String> list = Arrays.asList(arr);

不能 用这样构造出的list 进行 添加 、删除 操作。

但实际上,Arrays.asList() 返回的 ArrayList 并不是 java.util.ArrayList,而是 Arrays 的内部私有类 java.util.Arrays.ArrayList。虽然名字完全相同,都是 ArrayList,但两个类有着很大的不同。
Arrays.ArrayList 虽然有set()、get() 和 contains() 等方法,但却没有一个方法用来添加元素,因此它的大小是固定的。

如果想创建一个真正的list 需要,在new 出来的 ArrayList 构造出来。

List<String> list = new ArrayList<String>(Arrays.asList(arr));

2、不要在foreach里面进行元素的remove/add操作,remove请使用Iterator方式

我们都知道增加for循环即foreach循环其实就是根据list对象创建一个iterator迭代对象,用这个迭代对象来遍历list,相当于list对象中元素的遍历托管给了iterator,如果要对list进行增删操作,都必须经过iterator。
每次foreach循环时都有以下两个操作

iterator.hasNext(); //判读是否有下个元素
item = iterator.next(); //下个元素是什么,并把它赋给item。

List<String> a = new ArrayList<>();
        a.add("1");
        a.add("2");
        for (String temp : a) {
    
    
            if("1".equals(temp)){
    
    
                a.remove(temp);
            }
        }

上面代码在编译和运行时都不会报错,并且也能正常remove掉元素,但是如果将"1" 换成"2",运行时就会报ConcurrentModificationException.首选需要分析ArrayList的源码,ArrayList类继承自AbstractList类,该类中有一个成员变量:


protected transient int modCount = 0;
modCount用于记录变更次数,当add或者remove时,都会自增1

foreach时会调用ArrayList的iterator方法,该返回一个Itr类型的内部类,该内部类有几个需要注意的成员变量:


int cursor;       // index of next element to return
int expectedModCount = modCount;

cursor用于记录获取到哪个元素,expectedModCount用于记录变更次数,如果在iter过程中删除了一个元素,在调用iter.next()时会调用 Itr.checkForComdification()方法校验是否有变更:


final void checkForComodification() {
    
    
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

如果expectedModCount != modCount,就会报ConcurrentModificationException异常.

猜你喜欢

转载自blog.csdn.net/weixin_43975771/article/details/103949006