머리말
이 문서에서 우리는 List 인터페이스를 구현하는 또 다른 컨테이너 클래스, ArrayList를를 분석, 구현 클래스 목록이며, 기본이되는 구현이 배열은, 우리가 아래에서 자세히 분석 할 수 있습니다. PS : 몇 시간 전에 학교 실험실 코스가 블로그를 업데이트하지 않았습니다 오랜 시간 동안 등 일 플러스 최종 시험의 모든 종류를 설정하기 때문에 ...
1. 개요
가능해, RandomAccess ArrayList 클래스가 인터페이스를 구현, 랜덤 액세스를 지원합니다.
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
复制代码
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size;复制代码
2. 확장
주목해야한다 동작의 확장은 또한 스레드 안전 동작이다. 국경 간 접속의 문제가 배열 다중 스레드 환경에서 나타나지 않도록 라인이 문은 원자 동작 아니다. 그래서 는 HashMap처럼 ArrayList의 스레드 안전 컨테이너입니다 .
elementData[size++] = e;复制代码
다음은 새로운 요소는 소스 코드 및 확장 작업에 삽입한다 :
//插入新元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
//这里会产生数组越界问题,因为下面这行语句并不是一个原子操作
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
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;
//新容量为旧容量的1.5倍
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);
}复制代码
3. 분리 소자
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;
}复制代码
4. 르파
약 4.1 르파
르파 하나의 오류 메커니즘의 메커니즘 자바 컬렉션 (컬렉션). 다중 스레드는 내용의 동일한 세트에서 작동 할 때, 르파 이벤트를 생성 할 수 있습니다.
예를 들어 스레드 반복기는 수집 과정을 통해 통과 할 때, 세트는 다른 스레드에 의해 변경된 경우, 콘텐츠 후 예외의 ConcurrentModificationException이 르파 이벤트를 생성 발생한다하는 컬렉션에 액세스 쓰레드.
르파 4.2의 ArrayList에서
ArrayList에의 modCount는 구조의 변화의 수를 기록하는 데 사용 . 작동, 내부 배열 구조에서 모든 변경의 크기를 조정 부가 적어도 하나 개의 요소를 삭제하는 요소의 값을 그냥 구조의 변경 설정을 의미한다.
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();
}
}复制代码
시퀀스
transient Object[] elementData; // non-private to simplify nested class access复制代码
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();
}
}
}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();
}
}复制代码
ArrayList list = new ArrayList();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(list);复制代码
6. 요약
뷰의 소스 포인트에서의 ArrayList 제거) 일부 용지는 추가 (같은 몇몇 일반적으로 사용되는 방법으로, 내부 데이터 구조의 ArrayList를 분석 HashMap의보다 다소 더 간단 할 수있다 (). 또한 다중 스레드 환경이 스레드 안전 컨테이너가 다중 스레드 환경에서 사용하려는 경우, 또한 ArrayList에있는 르파 소개, 벡터으로 CopyOnWriteArrayList 또는 두 개의 컨테이너를 사용하는 것이 좋습니다 이유 논의 응용 프로그램과 ArrayList를 직렬화 문제.
마지막으로,이 문서의 단점을 지적, 서로 논의하기 위해 당신을 환영합니다.