要点:
1)数组实现 Object[]。
2)无限扩容。
3)非线程安全。
4)插入元素的时候可能扩容,删除元素时不会缩小容量,不使用索引的元素查找需要遍历数组,并使用equals比较。
构造:
1)默认构造方法使用默认容量,大小为10。
2)指定容量的构造方法。
代码如下:
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
public ArrayList() {
this(10);
}
3)指定一个集合作为参数,集合是Collection的子类。
代码如下:
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
size = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
if那句只是对toArray方法返回的数组有可能不是Object类型数组的情况进行检测。
增加:
1)因为是数组实现,ArrayList的代价会大一些,而且会考虑是否需要扩容,首先在原有元素个数上加一为minCapacity,用这个值和Ooject数组大小进行比较(容量),如果这个值大,那么就需要扩容了,将数组的size*1.5+1,如果此时还是minCapacity的话,那么新容量就用minCapacity来表示,然后就是生成新的容量的数组,原来的元素赋值进去即可,如果想更改扩容策略,继承ArrayList,重写ensureCapacity方法即可。
2)add(E)把新添加的元素放到数组的末尾,只需要使用常数的时间。
3)add(int,E)在数组指定位置添加元素,首先确定数组这个位置是否存在和容量是否允许,然后将指定位置后面的所有元素全部向后面移动一个位置,最后才将元素插入进指定位置,使用O(n)的时间代价。
删除:
删除分两种,删除的元素为空,和非空,但都需要遍历。
1)如果为空(null),首先遍历数组元素是否有为空,若有,将使用fastRemove方法删除,具体做法是,将此位置后面的元素全部向前移动一位,最后的那个留空,并可以gc回收了。
2)如果不为空,使用equals方法进行比较,找到了相应的元素后,同样进行faseRemove方法进行删除。
3)remove(int)删除指定位置的元素,这是数组的优势,大大提升了性能,仅仅只需要判断index是否越界,剩下的就是直接删除了,不需要遍历,所以性能很好。
获取单个对象:
get(int),首先判断是否越界,然后就是直接返回元素了,这也是数组的优势。
遍历:
常用的迭代器设计模式,iterator方法返回一个父类实现的迭代器。
1)迭代器的hasNext方法的作用是判断当前位置是否是数组最后一个位置,相等为false,否则为true。
2)迭代器next方法用于返回当前的元素,并把指针指向下一个元素,值得注意的是,每次使用next方法的时候,都会判断创建迭代器获取的这个容器的计数器modCount是否与此时的不相等,不相等说明集合的大小被修改过,如果是会抛出ConcurrentModificationException异常,如果相等调用get方法返回元素即可。
判断元素是否存在:
1)首先判断条件元素是否为空,是则遍历集合,有就返回true,否则false。
2)不为空,则使用equals方法,需要遍历集合。