欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > > 文章正文

ArrayList使用set或add方法添加指定元素抛出IndexOutOfBoundsException,

来源: javaer 分享于  点击 26433 次 点评:114

ArrayList使用set或add方法添加指定元素抛出IndexOutOfBoundsException,


问题

  • 直接使用arrayList通过add(int index,E e)添加指定位置的元素
ArrayList<String> array = new ArrayList<String>();
array.add(1,"hello world");
  • arraylist 调用clear()方法后通过set()指定位置的元素
ArrayList<String> array = new ArrayList<String>();
array.add("hello");
array.add("world");
array.clear();
array.set(2,"mitty");

上述两种情况都会出现IndexOutOfBoundsException,其实不单单是这两种情况,只要涉及到ArrayList中对index元素操作的方法都需要注意,下面就通过源码来分析原因。

原因

ArrayList生成对象如果不是集合copy,即:

public ArrayList(Collection<? extends E> collection)
{
    ...
}

也没有通过add按顺序添加元素或元素集合,即:

public boolean add(E object);

public boolean addAll(Collection<? extends E> collection) ;

ArrayList中的size是不会发生变化的,所以在指定index的时候一般会先判断数组下标是否越界,如:

public void add(int index, E object) {
        //ArrayList中真正存取元素的数组,所以本质上说,ArrayList是数组的包装类。
        Object[] a = array;
        //index反应数组真实元素个数,数组的大小比元素个数多。
        int s = size;
        //这里会判断数组的大小是否越界
        if (index > s || index < 0) {
            throwIndexOutOfBoundsException(index, s);
        }
        //小于size直接添加,大于则扩展数组的大小
        if (s < a.length) {
            System.arraycopy(a, index, a, index + 1, s - index);
        } else {
            // assert s == a.length;
            Object[] newArray = new Object[newCapacity(s)];
            System.arraycopy(a, 0, newArray, 0, index);
            System.arraycopy(a, index, newArray, index + 1, s - index);
            array = a = newArray;
        }
        a[index] = object;
        size = s + 1;
        modCount++;
    }

同样set(int index,E e)也会判断,但是开始添加了两个元素,那为什么第二种情况会发生呢?因为调用了clear()方法,clear方法会清空元素,并将size置为0,所以比较的时候就会;

 public void clear() {
        if (size != 0) {
            Arrays.fill(array, 0, size, null);
            size = 0;
            modCount++;
        }
    }

扩容的规则

private static final int MIN_CAPACITY_INCREMENT = 12;

private static int newCapacity(int currentCapacity) {
        int increment = (currentCapacity < (MIN_CAPACITY_INCREMENT / 2) ?
                MIN_CAPACITY_INCREMENT : currentCapacity >> 1);
        return currentCapacity + increment;
    }

结论

ArrayList实际上是数组的封装,而元素大小size是真实的反应ArrayList中元素的真实个数,元素的增加是按顺序增长的,size并不是数组的长度,所以在不确定ArrayList元素个数的情况下,需要先确定ArrayList的元素大小在去考虑对ArrayList指定元素的操作。

相关文章

    暂无相关文章

用户点评