ArrayList
1.简单介绍
ArrayList
是一个顺序容器,允许null值,
底层通过
数组实现,或者称为动态数组。get(),set() 等随机访问方法速度较快,add(),remove()等方法较慢。ArrayList是线程不安全的。
2.方法和源码
版本:java version "1.7.0_80"
1.几个属性如下
private static final int DEFAULT_CAPACITY = 10; // 默认数组长度
private static final Object[] EMPTY_ELEMENTDATA = {}; // 默认的初始化数组
private transient Object[] elementData; // 数组元素 此处未实现序列化
private int size; // 长度
2.初始化提供了3种构造方法
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA; //此处并没有默认10的长度 是在后面自动变长的一个机制中实现的
}
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); // 转成数组之后直接复制
}
关于上面的官方注释
点击打开链接
3.这个方法大概意思 把多余的空间去掉
public void trimToSize() {
modCount++; // 涉及到数组结构变化时的同步
if (size < elementData.length) {
elementData = Arrays.copyOf(elementData, size);
}
}
4.自动变长
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}在每个add方法调用时,都先调用了
ensureCapacityInternal(int size) 这个方法确保数组长度不小于size,而且每次扩容的长度都是原来的1.5倍。
5. add 和 remove
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
删除一个元素时,需要把它后面的元素前移,同时把该元素的引用置为null,销毁对象由GC负责。
6.序列化
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();
// Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size);
// Write out all elements in the proper order.
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA;
// Read in size, and any hidden stuff
s.defaultReadObject();
// Read in capacity
s.readInt(); // ignored
if (size > 0) {
// be like clone(), allocate array based upon size not capacity
ensureCapacityInternal(size);
Object[] a = elementData;
// Read in all elements in the proper order.
for (int i=0; i<size; i++) {
a[i] = s.readObject();
}
}
}
数组对象不会自动序列化到介质中,因为数组中实际存放的也是元素的引用,反序列化时不可能指向原来的对象。所以这里用writeobject和readobject手工序列化。
7.结构性变化时的同步
ArrayList中所有涉及结构性变化的方法中都增加了 modCount的值,内部成员类中定义的expectedModCount初始化为ArrayList的modCount的值。
主要作用就是在迭代操作时 避免一些结构性变化的危险操作。
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() { // 在内部类Itr中 同步的检查
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
8.ArrayList的遍历
public class Test {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
for(int i = 0; i < 10; i++){
list.add(i);
}
//直接打印
System.out.println(list.toString());
//for循环
System.out.println("for循环:");
for(int i = 0; i < list.size(); i++){
System.out.print(list.get(i) + " ");
}
//foreach
System.out.println("\nforeach:");
for(Integer i : list){
System.out.print(i + " ");
}
//iterator
System.out.println("\niterator:");
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
System.out.print(iterator.next() + " ");
}
//listIterator
System.out.println("\nlistIterator:");
ListIterator<Integer> listIterator = list.listIterator();
while(listIterator.hasNext()){
System.out.print(listIterator.next() + " ");
}
System.out.println();
while(listIterator.hasPrevious()){
System.out.print(listIterator.previous() + " ");
}
}
}主要使用 for循环下标,迭代器遍历(
Iterator和ListIterator),foreach遍历。
待补充...
转载请注明原文地址: https://ju.6miu.com/read-676283.html