이 기사는 ArrayList의 소스 코드를 분석합니다. 분석하기 전에 배열에 대해 이야기하겠습니다. 배열은 우리가 접촉 한 최초의 데이터 구조 중 하나 일 수 있습니다. 그들은 요소를 저장하기 위해 메모리의 연속 주소 공간을 나눕니다. 메모리를 직접 작동하므로 배열의 성능은 컬렉션 클래스의 성능보다 낫습니다. 이는 배열 사용의 주요 이점입니다. 그러나 우리는 배열에 치명적인 결함이 있으며, 즉 초기화 중에 배열 크기를 지정해야하며, 배열의 크기는 후속 작업에서 변경할 수 없다는 것을 알고 있습니다. 실제 상황에서, 우리는 처음에 저장해야 할 요소의 수를 알지 못하는 더 많은 것을 만나고 대신 컨테이너가 자체 용량을 자동으로 확장하여 더 많은 요소를 저장할 수 있기를 바랍니다. Arraylist는 이러한 요구를 매우 잘 충족시킬 수 있으며 스토리지 요소의 지속적인 증가에 적응하도록 크기를 자동으로 확장 할 수 있습니다. 기본 레이어는 배열을 기반으로 구현되므로 수정을 찾는 것이 빠르고 삽입이 느리다는 것과 같은 일부 배열 기능이 있습니다. 이 기사에서는 소스 코드를 깊이 들어 배열을 캡슐화하는 방법을 확인합니다. 먼저 회원 변수와 3 개의 주요 생성자를 살펴보십시오.
// 기본 초기화 용량 비공개 정적 최종 int default_capacity = 10; // 빈 객체 배열 비공개 정적 최종 오브젝트 [] empty_elementData = // 객체 배열 개인 과도 객체 [] elementData 수; // 초기 용량 공개 배열리스트에서 전달하기위한 생성자 메소드 (int inititalCapacity) {); if (InitialCapacity <0) {New New OregalArgumentException ( "불법 용량 :"+ 초기 범위); } // 지정된 용량의 새 개체 유형 배열 생성 is.elementData = 새 개체 [초기 커피 션];} // 매개 변수가없는 생성자 public arraylist () {super (); // 빈 배열 인스턴스를 ElementData로 전달하십시오. ElementData = empty_elementData;} // 외부 수집으로 전달하는 생성자 메소드 public arraylist (collection <? extends e> c) {// 수집 내부 배열의 참조 요소를 Collection ElementData = C.ToArray (); // 컬렉션 크기의 요소 수를 업데이트합니다 = ElementData.length; // 기준의 배열 유형을 판단하고 참조를 객체 배열 참조로 변환 if (elementData.getClass ()! = Object []. class) {elementData = arrays.copyof (elementData, size, object []. class); }}ArrayList의 내부 저장 구조는 객체 유형의 배열이므로 모든 유형의 요소를 저장할 수 있습니다. ArrayList를 구성 할 때 초기 크기가 전달되면 지정된 용량의 새 개체 배열이 생성됩니다. 초기 크기가 설정되지 않은 경우 메모리 공간을 할당하지 않고 빈 객체 배열을 사용한 다음 요소를 실제로 배치 할 때 메모리를 할당합니다. 추가, 삭제, 수정 및 검색 방법을 살펴 보겠습니다.
// 증가 (추가) public boolean add (e e) {// 추가하기 전에 배열을 확장 해야하는지 확인하면 최소 배열 길이는 크기 + 1 ensurecapacity internal (size + 1)입니다. // 배열 끝에 요소를 추가하십시오. ElementData [size ++] = e; return true;} // 증가 (삽입) public void add (int index, e element) {// 위치 범위 삽입 rangecheckforadd (index); // 용량이 확장되어야하는지 여부를 확인하십시오 (size + 1). // 삽입 위치 시스템 뒤에 요소를 움직입니다. ArrayCopy (ElementData, index, elementData, index + 1, size -index); // 새 값을 지정하십시오. elementData [index] = element; size ++;} // public e 제거 (int index) {// index는 Size RangeCheck (index)보다 클 수 없습니다. 모드 카운트 ++; e OldValue = ElementData (색인); int nummoved = size -index -1; if (nummoved> 0) {// 하나의 system.arraycopy (elementData, index+1, elementData, index, nummoved)로 인덱스 뒤에 요소를 앞으로 이동합니다. } // 빈 참조 elementData [-size] = null; OldValue;} // public e set (int index, e element) {// index가 크기 RangeCheck (index)보다 클 수 없습니다. e OldValue = ElementData (색인); // 새로운 요소로 바꾸십시오. return OldValue;} // public e get (int index) {// index는 크기 RangeCheck (index)보다 클 수 없습니다. // 지정된 위치 요소를 반환하십시오. 요소 리턴 요소 data (index);} 요소가 컬렉션에 추가 될 때마다 먼저 용량이 충분한 지 확인합니다. 그렇지 않으면 용량이 확장됩니다. 용량 확장에 대한 세부 사항은 아래에서 설명합니다. 먼저 추가, 삭제, 수정 및 확인 시점에주의를 기울일 특정 요점을 살펴 보겠습니다.
추가 (추가) :이 요소를 끝에 추가하십시오. 빠른 작동.
추가 (삽입) : 삽입 위치 뒤의 요소가 움직여야하고 배열의 복사가 관련되어 작업 속도가 느려집니다.
삭제 : 삭제 위치 뒤의 요소를 앞으로 이동해야하므로 배열 사본도 설계되므로 작업 속도가 느립니다.
변경 : 요소 이동 또는 어레이 복사를 포함하지 않고 지정된 위치에서 요소를 직접 수정하면 작동이 빠릅니다.
점검 : 지정된 첨자의 배열 요소를 직접 반환하면 작동이 빠릅니다.
소스 코드에서 검색 및 수정은 배열 첨자에 직접 배치되므로 요소 이동 및 배열 복사가 포함되지 않으므로 더 빠릅니다. 그러나 요소를 움직여야하므로 배열 복사가 포함되므로 작업 속도가 느려집니다. 또한 각 추가 작업은 배열 확장을 수행 할 수도 있으며, 이는 성능에도 영향을 미칩니다. ArrayList가 용량을 동적으로 확장하는 방법을 살펴 보겠습니다.
Private void ensurecApacityInternal (int mincapacity) {// 배열이 아직 비어있는 경우 (elementData == empall_elementData) {// 기본 용량과 비교하면 더 큰 값 mincapacity = math.max (default_capacity, mincapacity); } // 배열이 초기화 된 경우이 단계를 수행하십시오. // 최소 용량이 배열 길이보다 큰 경우 배열을 증폭시켜 (minCapacity -ElementData.Length> 0) {grow (mincapacity); }} // 컬렉션의 최대 용량 개인 정적 최종 최종 최종 최종 최종 최종 최종 최종 최종 int max_array_size = integer.max_value -8; 배열 길이 개인 void grow (int mincapacity) {// 배열의 원래 용량을 얻습니다. // 새 배열의 용량, 원래의 절반을 원래 기준으로 추가 int newCapacity = OldCapacity + (OldCapacity >> 1); // 새로운 용량이 최소 용량보다 적은지 확인하십시오. } // 새 용량이 최대 배열 용량을 초과하는지 확인합니다. } // 원래 배열을 새 배열에 복사하십시오. elementData = arrays.copyof (elementData, newCapacity);} 요소를 추가하기 전에 EnseRecapacitysInternal은 수집 용량 확인을 요청합니다. 이 방법에서는 현재 컬렉션의 내부 배열이 여전히 빈 배열인지 확인합니다. 그렇다면 기본 크기가 10 인 새 개체 배열을 만듭니다. 그렇지 않은 경우 현재 컬렉션이 초기화되었음을 증명합니다. 그런 다음 inricexplicitcapacity 메소드를 호출하여 현재 배열의 용량이 최소 필수 용량을 충족하는지 확인하십시오. 만족하지 않으면 성장 방법을 호출하여 확장하십시오. 성장 방법에서는 각 확장이 원래 배열 길이의 절반을 증가시키는 것임을 알 수 있습니다. 확장은 실제로 더 큰 용량의 새 배열을 생성하고 원래 배열의 모든 요소를 새 배열에 복사 한 다음 원래 배열을 버리고 새 배열을 사용하는 것입니다. 지금까지 Arraylist에서보다 일반적으로 사용되는 방법과 주목할만한 주요 포인트를 분석했습니다.
1. ArrayList의 기본 구현은 배열을 기반으로하므로 지정된 첨자의 검색 및 수정이 더 빠르지 만 삭제 및 삽입 작업은 느려집니다.
2. Arraylist를 구성 할 때는 확장으로 인한 배열 복사 작업을 줄이기 위해 가능한 한 많은 용량을 지정하십시오. 크기를 모르는 경우 기본 용량을 10에 할당 할 수 있습니다.
3. 요소를 추가하기 전에 용량 확장이 필요한지 확인하십시오. 각 용량 확장은 원래 용량의 절반입니다.
4. 첨자 작업이 작동 할 때마다 보안 검사가 수행됩니다. 배열이 한계를 벗어난 경우 예외가 즉시 발생됩니다.
5. ArrayList의 모든 방법은 동기화되지 않으므로 스레드 안전하지 않습니다.
6. 위의 분석은 JDK1.7을 기반으로하며 다른 버전에는 약간의 차이가 있으므로 일반화 할 수 없습니다.
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.