Java 집합 상세 설명 - Array List
ArrayList 는 AbstractList 에서 계승 하여 List 인 터 페 이 스 를 실현 하 였 으 며, 본질 적 으로 기본 초기 길이 가 10 이 며, 자동 확장 을 지원 하 는 배열 입 니 다.ArrayList 비 스 레 드 안전, 다 중 스 레 드 환경 에서 작업 하려 면 개발 자가 스 레 드 안전 을 확보 해 야 합 니 다.
관건 변수 와 상수
//
private static final int DEFAULT_CAPACITY = 10;
// , ArrayList .
transient Object[] elementData;
초기 화
Array List 는 세 가지 초기 화 방법 을 제공 합 니 다.
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
이 방식 으로 ArrayList 를 만 들 때
elementData
빈 배열 로 초기 화 하고 DEFAULT_CAPACITY = 10
초기 용량 으로 사용 합 니 다. /**
* Constructs an empty list with the specified initial capacity.
*
* @param initialCapacity the initial capacity of the list
* @throws IllegalArgumentException if the specified initial capacity
* is negative
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
초기 화 시 초기 용량 을 입력 하고
elementData
길 이 를 대응 하 는 배열 로 초기 화 합 니 다. 0 에 들 어 갈 때 첫 번 째 초기 화 방법 과 같 고 0 보다 작은 용량 으로 들 어 갈 때 IllegalArgumentException
이상 을 던 집 니 다. /**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
public ArrayList(Collection extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
이 방법 은 들 어 오 는 집합 을 배열 로 바 꾸 고
elementData
에 값 을 부여 하 는 것 을 잘 이해 할 수 있다. 관건 은 if (elementData.getClass() != Object[].class)
이 줄 코드 에 이 판단 을 더 한 의 도 는 무엇 입 니까?주석 의 의 미 는 c.toArray()
되 돌아 오 는 것 이 꼭 Object [] 유형 이 아니 라 는 것 입 니 다. 여기 서 알 아 봐 야 합 니 다 JDK-6260652 Bug예 를 들 어 다음 코드 를 사용 하여 Array List 를 만 듭 니 다.
List
Arrays.asList(new String[]{"123"}).toArray().getClass()
유형 은 String[]
유형 이 아 닌 Object[]
유형 으로 되 돌아 가 고, 재 집행 objs[0] = new Object();
하면 java.lang.ArrayStoreException
이상 을 던진다.구체 적 인 원인 은
Arrays#ArrayList.toArray()
방법 을 보아 야 한다. public T[] toArray(T[] a) {
int size = size();
if (a.length < size)
return Arrays.copyOf(this.a, size,
(Class extends T[]>) a.getClass());
System.arraycopy(this.a, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
상기 코드 에서 보 듯 이
Arrays#ArrayList.toArray()
는 T[]
유형 을 되 돌려 주 고 String
배열 에 들 어 오 면 되 돌아 오 는 배열 유형 은 String[]
유형 이다.하나의 String[]
유형 배열 에 대해 하나의 Object
값 을 부여 하면 오류 가 발생 할 수 있 습 니 다.따라서 위의 판단 이 있 고
Object[]
유형 인지 판단 하 며 그렇지 않 으 면 배열 을 Object[]
유형 으로 전환 하여 후속 할당 시 java.lang.ArrayStoreException
이상 이 발생 하지 않도록 한다.획득
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
ArrayList
아래 표 시 를 통 해 요 소 를 얻 을 때 먼저 index
경 계 를 넘 었 는 지 여 부 를 판단 하고 경 계 를 넘 으 면 IndexOutOfBoundsException
이상 을 던 집 니 다. 그렇지 않 으 면 아래 표 시 된 요 소 를 되 돌려 줍 니 다.덧붙이다
Array List 에 요 소 를 추가 하 는 방법 은 두 가지 가 있 습 니 다.
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++;
}
// index
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// , elementData , DEFAULT_CAPACITY, minCapacity
// minCapacity
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
// , , grow
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;
// , 50%
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);
}
먼저
index
경 계 를 넘 었 는 지, 경 계 를 넘 어 IndexOutOfBoundsException
이상 을 던 진 다음 에 배열 의 확장 이 필요 한 지 판단 합 니 다. 확장 이 필요 하 다 면 확장 후 요 소 를 지정 index
에 추가 합 니 다. 구체 적 으로 코드 설명 을 보십시오. public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
주요 절 차 는 위의 방법 과 유사 하여 붙 이지 않 는 다.
삭제
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;
}
일반적인 조작 은 첫 번 째 단계 에서 먼저 경 계 를 넘 었 는 지 여 부 를 판단 한다.이 곳
modCount
변 수 는 구조 변화 가 발생 한 횟수 를 통계 하 는 데 사 용 됩 니 다. ArrayList
의 값 이 예상 과 맞지 않 으 면 modCount
이상 을 던 집 니 다. 보통 옮 겨 다 닐 때 ConcurrentModificationException
요 소 를 삭제 하거나 추가 하 는 장면 이 나타 납 니 다.그 다음 에 대응 하 는 ArrayList
의 값 을 얻 고 이동 할 요소 의 수량 을 계산 합 니 다. index
이 있 으 면 numMoved > 0
을 통 해 System.arraycopy
다음 index + 1
요 소 를 numMoved
위치 로 복사 합 니 다.만약 index
, 직접 할당 numMoved == 0
, GC 회수 대기 public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
private void fastRemove(int index) {
modCount++;
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
}
이 방법 은 대상 에 전송 되 어
null
에 대응 하 는 첫 번 째 대상 을 찾 은 후 삭제 합 니 다. 절차 와 위의 방법 은 차이 가 많 지 않 습 니 다.바꾸다
지정 한 위치의 요소 바 꾸 기
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
먼저
ArrayList
선 을 넘 었 는 지 여 부 를 판단 하고 선 을 넘 어 index
이상 을 던 졌 으 며, 선 을 넘 지 않 으 면 IndexOutOfBoundsException
에서 대응 elementData
의 값 을 얻 고 대응 index
의 값 을 새 값 으로 설정 한 후 되 돌려 index
modCount 배열 구조 변경 횟수 를 기록 하 는 데 사용 되 며, 매번 요 소 를 추가 하거나 삭제 할 때마다 + 1. 교체 기 를 사용 할 때
oldValue
예상 과 일치 하지 않 으 면 modCount
이상 을 던 집 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.