나는 전에 문장을 읽었고, 그것은 매우 좋았습니다. 누군가 읽기 소스 코드의 사용이 무엇인지 물었습니까? 특정 기능을 구현하고 프로그래밍 수준을 향상시키기 위해 다른 사람의 디자인 아이디어를 배우십시오.
예, 모두가 기능을 구현합니다. 다른 사람들마다 다른 디자인 아이디어가 있습니다. 어떤 사람들은 10,000 줄의 코드를 사용하고 어떤 사람들은 5,000 줄을 사용합니다. 어떤 사람들은 수십 초 동안 코드를 실행 해야하는 반면, 다른 사람들은 몇 초 밖에 걸리지 않아야합니다. . 아래 주제에 접근합시다.
이 기사의 주요 내용 :
jdk 1.8을 기반으로 한 Arraylist 구현에 대한 자세한 의견.
interator iterator subrist part는 자세히 설명되지 않았으며 다른 소스 코드 해석에 배치됩니다. 여기서 우리는 배열리스트 자체의 구현에 중점을 둡니다.
・표준 주석이 사용되지 않으며, 코드의 압입이 쉽게 소개되도록 적절하게 조정됩니다.
import java.util.abstractlist; import java.util.arrays; import java.util.bitset; import java.util.collection; import java.util.comparator; import java.util.concurrentmodificationexception; import java.util.tertorator import java.util.list; java.util.nosuchelementexception; import java.util.objects; import java.util.randomaccess; import java.util.spliterator; import java.util.function.consumer; import java.util.function.predicate; import java.util.function. 크기 조정할 수있는 목록 인터페이스의 배열 구현. 모든 선택적 목록 작업을 구현하고 NULL을 포함한 모든 요소를 반복 할 수 있도록합니다. * 목록 인터페이스 외에도이 클래스는 배열의 크기를 조작하여 배열의 크기를 목록에 저장하는 방법을 제공합니다. * * 시간 복잡성 : * 메소드 크기, ISEMPTY, GET, SET, ITERATOR 및 LISTITERATOR에 대한 호출은 일정한 시간입니다. * 추가 및 삭제의 시간 복잡성은 O (N)입니다. 다른 모든 작업은 선형 시간 복잡성입니다. * * 용량 : * 각 배열리스트는 용량을 가지며 용량 크기는 최소한 목록 요소의 길이이며 기본 초기화는 10입니다. * 용량은 자동으로 증가 할 수 있습니다. * 배열에 많은 요소가 있다는 것을 미리 알고 있다면, 나중에 자동 용량 성장의 오버 헤드를 줄이기 위해 요소를 추가하기 전에 ensurecapacity () 방법을 호출하여 용량을 미리 늘릴 수 있습니다. *이 용량은 초기 용량을 가진 생성자에 의해 초기화 될 수 있습니다. * * 스레드는 안전하지 않습니다 : * ArrayList는 스레드 안전하지 않습니다. * 멀티 스레드에 적용 해야하는 경우, 동기화를 외부 적으로 수행해야합니다 * * modcount : * AbstractList에 정의 : 보호 된 과도 int modcount = 0; *이 목록은 구조적으로 수정되었습니다. 구조 수정은 목록의 크기를 변경하거나 목록을 방해하여 진행중인 반복이 잘못된 결과를 낳는 것을 의미합니다. *이 필드는 반복자 및 목록 반복자 구현에 의해 사용됩니다. *이 필드의 값이 실수로 변경되면 반복자 (또는 목록 반복자)는 다음, 다음, 제거, 이전, 설정 또는 추가 작업에 대한 응답으로 동시 변형 외환을 던집니다. * 반복 중에 동시 수정에 직면하면 비 결정적 행동보다는 빠른 실패 행동을 제공합니다. * 서브 클래스 가이 필드를 사용하는지 여부는 선택 사항입니다. * 서브 클래스가 빠른 실패 반복기 (및 목록 반복자)를 제공하려면이 필드를 추가 (int, e) 및 제거 (int) 메소드 (및 기타 메소드를 재정의하여 목록 구조의 수정)에 추가합니다. * 추가 (int, e) 또는 제거 (int)를 추가 할 단일 통화 수는이 필드에 1을 초과하지 않아야합니다. 그렇지 않으면 반복자 (및 목록 반복자)는 가짜 동시 모형화 외과를합니다. * 구현이 빠른 실패 반복기를 제공하지 않으려면이 필드를 무시할 수 있습니다. * * 과도 : * 기본적으로 객체의 모든 멤버 변수가 지속됩니다. 경우에 따라 객체의 일부 멤버 변수를 지속하지 않으려면 과도 키워드를 사용하여 태그를 붙일 수 있습니다.이 키워드는 java (jdk 1.8) */public class arraylist <e>에 예약 된 단어 인 AbstractList <e> imments <e>, randomaccess, clonable, java.io.serializable = {serializable = serializable = {public anderializable = intractlist <e>를 확장 할 수 있습니다. 8683452581122892189L; // 기본 초기 용량 개인 정적 최종 최종 int default_capacity = 10; // 빈 인스턴스와 빈 배열 인스턴스를 공유하는 데 사용됩니다. 개인 정적 최종 개체 [] empty_elementData = {}; // 기본 빈 배열 비공개 정적 최종 오브젝트 [] defaultCapacity_Empty_ElementData = {}; // 오른쪽의 경우, 요소 배열, 패키지 액세스 권한은 과도 객체 [] ElementData; // 크기, Java는 객체 개인 int 크기를 생성 할 때 int 0을 초기화합니다. // 초기화 용량의 생성자를 지정된 숫자로 설정하면 음수 숫자가 공개 ArrayList (int initialCapacity) {if (InitialCapacity> 0) {this.elementData = 새 개체 [초기 범위]; } else if (initialCapacity == 0) {this.ElementData = empty_elementData; } else {throw new ImperalArgumentException ( "불법 용량 :"+초기 범위); }} // 기본 생성자, Control Array를 사용하여 public arraylist () {this.elementData = defaultCapacity_Empty_ElementData; } // 컬렉션의 반복자 순서대로 컬렉션에 요소가 포함 된 목록을 구성합니다 (collection <? extends e> c) {elementData = c.toArray (); if (size = elementData.length)! = 0) {// C.ToArray (오류) 리턴 객체 [] (java 버그 번호 6260652 참조) if (elementData.getClass ()! = Object []. class) elementData = arrays.copyof (ElementData, size, object []. class); } else {// 빈 배열을 사용하십시오. }} // 용량은 종종 실제 요소 수보다 크기 때문에. 메모리가 단단 해지면이 방법을 호출하여 예약 된 위치를 삭제하고 실제 요소 수로 용량을 조정할 수 있습니다. // 요소가 추가되지 않으면 공간 공개 void trimTosize () {modcount ++; if (size <ElementData.length) {elementData = (size == 0)? empty_elementData : arrays.copyof (elementData, size); }} // 지정된 매개 변수로 배열 용량을 설정하여 공개 void ensurecApacity (int mincapacity) {// 배열이 비어 있으면 사전 0, 그렇지 않으면 기본 값 (10) int minexpand = (elementData! = defaultCapacity_Empty_ElementData)로 이동하십시오. 0 : default_capacity; // 매개 변수가 사전 설정 용량보다 큰 경우이 매개 변수를 사용하여 배열 용량을 추가로 설정하십시오. }} // 요소를 추가 할 때 배열 용량 개인 무효 void ensurecapacity internal (int mincapacity) {// 기본값과 더 큰 매개 변수를 용량 사전 값으로 사용하십시오. } restexplicitCapicacity (mincapacity); } // 매개 변수가 배열 용량보다 큰 경우 배열 용량을 늘리십시오 프라이버시 void inricexplicitCapacity (int mincapacity) {modcount ++; if (minCapacity -ElementData.Length> 0) 성장 (MinCapacity); } // 배열의 최대 용량은 메모리 오버플로 (VM 메모리 한계) 개인 정적 최종 최종 최종 최종 int max_array_size = integer.max_value -8; // 매개 변수에서 지정된 요소 수를 최소한 보유 할 수있는 용량을 늘리십시오. Private Void Grow (int mincapacity) {int OldCapacity = elementData.length; // 사전 설정 용량을 반으로 int int newCapacity = OldCapacity + (OldCapacity >> 1); // (newCapacity -MinCapacity <0) // 즉, newCapacity <mincapacity newCapacity = minCapacity; // 사전 설정 값이 기본 최대값보다 큰 경우 (newCapacity -Max_Array_Size> 0) newCapacity = hugecapacity (mincapacity); elementData = arrays.copyof (ElementData, newCapacity); } // 오버플로되는지 확인합니다. 오버플로가없는 경우 최대 정수 값을 반환하십시오 (Java의 int는 4 바이트이므로 최대 값은 0x7ffffffff) 또는 기본 최대 값 개인 정적 int hugecapacity (int mincapacity) {if (mincapacity <0) // 오버 플로우 뉴저지 (newfmoreerror); return (mincapacity> max_array_size)? integer.max_value : max_array_size; } // 배열 크기를 반환 public int size () {return size; } // 빈 공개 부울 isempty () {return size == 0; } // 숫자가 포함되어 있는지 여부, return bool public boolean cotains (object o) {return indexof (o)> = 0; } // 배열의 첫 번째 모양에서 값을 반환하면 NULL인지 여부에 따라 다른 방식으로 판단됩니다. 존재하지 않으면 -1을 반환합니다. 시간 복잡성은 o (n) public int indexof (object o) {if (o == null) {for (int i = 0; i <size; i ++) if (elementData [i] == null) 반환 i; } else {for (int i = 0; i <size; i ++) if (o.equals (elementData [i]) return i; } 반환 -1; } // 배열에 나타날 때 마지막으로 값을 반환합니다. 존재하지 않으면 -1을 반환합니다. 시간 복잡성은 o (n) public int lastIndexof (object o) {if (o == null) {for (int i = size-1; i> = 0; i-) if (elementData [i] == null) 반환 i; } else {for (int i = size-1; i> = 0; i-) if (o.equals (elementData [i]) return i; } 반환 -1; } // 사본을 반환하면 요소 자체가 복사되지 않았으며 복사 프로세스의 배열이 공개 오브젝트 클론 () {try {arraylist <?> v = (ArrayList <?>) super.clone (); v.elementData = arrays.copyof (ElementData, size); v.modcount = 0; 반환 v; } catch (clonenotsupportedException e) {새로운 내부 테러 (e)를 던지십시오. }} // 객체 배열로 변환하고 array.copyof () 메소드 public Object [] toArray () {return array.copyof (elementData, size); } // 배열을 반환하고 런타임을 사용하여 유형을 결정하고 배열에는이 목록에 모든 요소가 포함되어 있습니다 (첫 번째부터 마지막 요소까지) // 반환 된 배열 용량은 매개 변수 와이 배열의 더 큰 값에 의해 결정됩니다 @SuppressWarnings ( "Checked") public <t> t [] toArray (t []) {a.lengther (a.lengther <size) {). Arrays.copyof (ElementData, size, a.getClass ()); System.ArrayCopy (ElementData, 0, A, 0, 크기); if (a.length> size) a [size] = null; 반환 a; } // 지정된 위치의 값을 반환합니다. 배열이기 때문에 특히 빠른 @SuppressWarnings ( "확인되지 않은") e ElementData (int index) {return (e) elementData [index]; } // 지정된 위치의 값을 반환하지만 위치 수가 배열 길이를 초과하는지 여부를 확인하십시오. 공개 e (int index) {rangecheck (index); 반환 요소 데이터 (인덱스); } // 지정된 위치를 새 값으로 설정하고 이전 값을 반환하려면이 위치가 배열 길이 공개 E 세트 (int index, e element)를 초과하는지 확인하십시오. {rangecheck (index); e OldValue = ElementData (색인); ElementData [index] = 요소; OldValue를 반환하십시오. } // 값을 추가하여 먼저 용량 public boolean add (e e) {ensurecapacitys internal (size + 1); ElementData [size ++] = e; 진실을 반환하십시오. } // 지정된 위치에 값을 추가하고 추가 된 위치 및 용량 public void add (int index, e element) {rangecheckforadd (index); ensurecapacity internal (size + 1); // public static void arraycopy (객체 src, int srcpos, 객체 dest, int destpos, int length) // src : 소스 배열; SRCPOS : 복사 할 소스 배열의 시작 위치; 목적지 : 목적지 배열; DESTPOS : 대상 배열의 시작 위치; 길이 : 복사 길이 System.ArrayCopy (ElementData, Index, ElementData, Index + 1, Size -Index); ElementData [index] = 요소; 크기 ++; } // 지정된 위치의 값을 삭제하고 추가 된 위치를 점검하고 이전 값 공개 e 제거 (int index) {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를 반환합니다. } // 지정된 요소가 먼저 나타나는 위치를 삭제합니다. 공개 부울 제거 (object o) {if (o == null) {for (int index = 0; index <size; index ++) if (elementData [index] == null) {fastremove (index); 진실을 반환하십시오. }} else {for (int index = 0; index <size; index ++) if (o.equals (elementData [index]) {fastremove (index); 진실을 반환하십시오. }} 거짓을 반환합니다. } // 지정된 위치에서 값을 빠르게 삭제합니다. Fast라고 불리는 이유는 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; // GC가 작업을 수행하도록 지우십시오} // 배열을 지우고 각 값을 널로 설정하여 쓰레기 수집을 용이하게합니다 (재설정과 달리 배열의 기본 크기는 변경되면 재설정되지 않습니다) public void clear () {modcount ++; for (int i = 0; i <size; i ++) elementData [i] = null; 크기 = 0; } // 컬렉션의 요소를 끝까지 추가하고 추가 할 컬렉션이 비어 있으면 False Public Boolean addall (collection <? extends e> c) {object [] a = c.toArray (); int numnew = a.length; ensurecapacity internal (size + numnew); System.ArrayCopy (A, 0, ElementData, Size, Numnew); 크기 += numnew; NumNew! = 0을 반환합니다. } // 함수는 위와 동일하며 공개 부울 Addall (int index, collection <? extends e> c) {rangecheckforadd (index); 개체 [] a = c.toArray (); // 추가 할 배열 int numnew = a.length; // 추가 할 배열의 길이는 ensurecapacitysInternal (size + numnew); // 용량 int nummoved = size -index; // 이동하지 않는 길이 (이전 부분) if (nummoved> 0) // 이동할 필요가없는 경우 자체적으로 복사하여 배열의 뒷 부분을 올바른 위치 시스템으로 이동합니다 (ElementData, index, elementData, index + numnew, nummoved); System.ArrayCopy (A, 0, ElementData, Index, Numnew); // 변경된 원래 배열 크기의 중간에 새 배열을 추가합니다. += numnew; NumNew! = 0을 반환합니다. } // 지정된 범위 요소를 삭제합니다. 매개 변수는 시작 및 종료 위치 보호 보호 된 void Removerange (int fromIndex, int toIndex) {modcount ++; int nummoved = size -toindex; // 후자의 섹션에 의해 유지되는 길이. ArrayCopy (ElementData, toIndex, elementData, fromIndex, nummoved); int newsize = size- (toindex -fromindex); for (int i = newsize; i <size; i ++) {elementData [i] = null; } size = Newsize; } // 요소를 추가 할 때 숫자가 배열의 길이를 초과하는지 확인하십시오 비공개 void rangecheck (int index) {if (index> = size) 새 IndexOfBoundSexception (outOfBoundSMSG (index)); } // private void rangecheckforadd (int index) {if (index> size || index <0)가 새로운 indexOutOfBoundSexception (OutOfBoundSmsg (index))을 확인합니다. } // 제외 된 예외의 세부 사항 비공개 문자열 outOfBoundsmsg (int index)) {return "index :"+index+", size :"+size; } // 지정된 컬렉션의 요소를 삭제하여 public boolean removeall (collection <?> c) {objects.requirenonnull (c); // 매개 변수가 널 리턴 batchremove인지 확인 (c, false); } // 지정된 컬렉션의 요소 만 유지합니다. public boolean retainall (collection <?> c) {objects.requirenonnull (c); 반환 BatchRemove (C, True); }/** * 소스 코드 해석 http://anxpp.com/ * @param 완료 완료되면 지정된 컬렉션의 요소 값이 배열에서 유지되며 거짓으로 지정된 컬렉션의 요소 값이 배열에서 삭제됩니다. * @배열의 중복 요소는 삭제됩니다 (한 번 또는 여러 번 삭제되지 않고) 삭제되며 삭제 작업은 true */ private boolean batchremove (collection <?> c, boolean applement) {final object [] elementData = this.ElementData; int r = 0, w = 0; 부울 수정 = 거짓; {// 배열을 통과 하고이 컬렉션이 해당 값이 포함되어 있는지 확인하고, 배열의 전면으로 유지 될 값을 이동시키고, w의 마지막 값은 유지 될 요소의 수입니다. 삭제 된 경우 삭제 된 경우 (; r <size; r ++) if (c.contains (elementData [r]) == 보완) 요소 data [w ++] = ElementData [r]; } 마지막으로 {// 예외가 발생하기 전에 예상 작업이 예상 작업을 완료 할 수 있는지 확인하고 트래버지되지 않은 부분이 뒷면에 연결됩니다. // r! = 크기는 오류가 발생할 수 있음을 의미합니다. c.crantains (elementData [r]) {system.arraycopy (elementData, r, elementData, w, r); W += 크기 -R; } // w == 크기가 있다면 : 모든 요소가 유지되므로 삭제 작업이 발생하지 않으므로 False가 반환됩니다. 그렇지 않으면, true 및 배열 // w! = 크기가 반환 될 때, 시도 블록이 예외를 던지더라도, w는 항상 보유 할 이전 부분의 길이이며 (w! = size) {(int i = w; i <size; i ++) elementData [i] = null; modcount += size -w; // 변경된 횟수가 크기 = w; // 새 크기는 보존 된 요소 수입니다. }} 리턴 수정; } // 배열 인스턴스의 상태를 스트림에 저장합니다 (즉, 직렬화 됨). Writ s.defaultWriteObject (); // 기본 사막화/직렬화 프로세스를 실행합니다. 현재 클래스의 비 정적 및 비 번역 필드를이 스트림에 작성하십시오. // (int i = 0; i <size; i ++) {s.writeObject (elementData [i]); } if (modCount! = excliteModCount) {새 동시 동의 modificationException (); }} // 위의 내용은 작성되었으며 이것은 읽습니다. private void readObject (java.io.objectinputStream s)는 java.io.ioexception, classNotFoundException {elementData = empty_elementData; // 기본 직렬화/사막화 프로세스 수행 S.DefaultReadObject (); // 배열 길이에서 읽습니다. s.readint (); if (size> 0) {ensurecapacity internal (size); 객체 [] a = elementData; // (int i = 0; i <size; i ++) {a [i] = s.readobject (); }}}} // return listiterator, 시작 위치는 지정된 매개 변수 공개 public listiterator <e> listiterator (int index) {if (index <0 || index> size) 던지기 새 indexOutOfBoundSexception ( "index :"+index); 새로운 Listitr (색인)를 반환합니다. } // return listIterator, 시작 위치는 0 public listiterator <e> listiterator () {return new Listitr (0); } // 일반 반복자 공개 반복자를 반환합니다 <e> iterator () {return new itr (); } // 일반 반복자는 개인 클래스 ITR을 구현합니다. iterator <e> {int cursor; // 커서, 다음 요소의 색인 인 기본 초기화는 0 int lastret = -1; // 마지막으로 액세스 한 요소의 위치는 int exclingModCount = modCount입니다. // 반복 프로세스가 수정 된 배열을 실행하지 않으면 예외가 발생됩니다. } // 다음 요소 @suppresswarnings ( "선택 취소") public e next () {checkforcomodification (); // 배열이 수정되었는지 확인 int i = cursor; if (i> = size) 새 nosuchelementException ()을 던지십시오. Object [] ElementData = ArrayList.this.elementData; if (i> = ElementData.length) Throw New ConcurrentModificationException (); 커서 = i + 1; // 커서를 뒤로 이동합니다 (e) elementData [lastret = i]; // 액세스 위치를 설정 하고이 값을 반환} // 요소 삭제 public void remove () {if (lastret <0) strach new nelegalstateException (); CheckforComodification (); // 배열이 수정되었는지 확인 try {arraylist.this.remove (lastret); 커서 = lastret; lastret = -1; 예상 modCount = modCount; } catch (indexOutOfBoundSexception ex) {throw new concurrentModificationException (); }} @override @suppresswarnings ( "확인되지 않은") 공개 void foreachremaining (소비자 <? super e> 소비자) {objects.requirenonnull (소비자); 최종 int size = arraylist.this.size; int i = 커서; if (i> = size) {return; } final object [] elementData = arrayList.this.elementData; if (i> = ElementData.length) {throw new concurrentModificationException (); } while (i! = size && modcount == expectModCount) {consumer.accept ((e) emectData [i ++]); } cursor = i; lastret = i -1; CheckforComodification (); } // 배열이 수정되었는지 확인 최종 void checkforcomodification () {if (modcount! = exclingModCount) 던지기 new concurrentModificationException (); }} // listiterator iterator implements private class listitr extends itr rements lestiterator <e> {listitr (int index) {super (); 커서 = 색인; } public boolean hasprevious () {return cursor! = 0; } public int nextIndex () {return cursor; } public int previousIndex () {return cursor -1; } @SuppressWarnings ( "확인되지 않은") public e previous () {checkforcomodification (); int i = 커서 -1; if (i <0) 새 nosuchelementException ()을 던지십시오. Object [] ElementData = ArrayList.this.elementData; if (i> = ElementData.length) Throw New ConcurrentModificationException (); 커서 = i; return (e) ElementData [lastret = i]; } public void set (e e) {if (lastret <0) Throw New ImperalStateException (); CheckforComodification (); try {arraylist.this.set (lastret, e); } catch (indexOutOfBoundSexception ex) {throw new concurrentModificationException (); }} public void add (e e) {checkforcomodification (); {int i = 커서; arraylist.this.add (i, e); 커서 = i + 1; lastret = -1; 예상 modCount = modCount; } catch (indexOutOfBoundSexception ex) {throw new concurrentModificationException (); }}} // 지정된 범위 공개 목록의 서브 어레이를 반환합니다 <E> Sublist (int fromIndex, int toIndex) {subStrangeCheck (FromIndex, toIndex, size); 새 Subrist (this, 0, fromIndex, toIndex)를 반환합니다. } // 보안 검사 정적 무효 SubStranGeCheck (int fromIndex, int toIndex, int size) {if (fromIndex <0) 새 indexOutOfBoundSexception ( "fromIndex =" + fromIndex); if (toIndex> size) 새로운 IndexOutOfBoundSexception을 던지십시오 ( "toIndex =" + toIndex); if (fromindex> toindex) 새로운 불법 불법 행위 렉싱 ( "Fromindex (" + fromindex + ")> toindex (" + toindex + ")"); } // subarray private class subrist 확장 actractList <e> randomAccess {private final acblackList <e> parent; 개인 최종 INT ParentOffset; 개인 최종 INT 오프셋; int 크기; Subrist (AbstractList <e> parent, int offset, int fromIndex, int toIndex) {this.parent = parent; this.parentOffset = FromIndex; this.offset = Offset + FromIndex; this.size = toindex- FromIndex; this.modcount = arraylist.this.modcount; } public e set (int index, e e) {rangecheck (index); CheckforComodification (); e OldValue = arraylist.this.elementData (오프셋 + 색인); ArrayList.this.elementData [오프셋 + 색인] = e; OldValue를 반환하십시오. } public e get (int index) {rangecheck (index); CheckforComodification (); RETURN arrayList.this.elementData (오프셋 + 색인); } public int size () {checkforcomodification (); 이 iscize를 반환하십시오. } public void add (int index, e e) {rangecheckforadd (index); CheckforComodification (); parent.add (parentoffset + index, e); this.modcount = parent.modcount; this.size ++; } public e remove (int index) {rangecheck (index); CheckforComodification (); e result = parent.remove (parentoffset + index); this.modcount = parent.modcount; this.size--; 반환 결과; } Protected Void Removerange (int fromIndex, int toIndex) {checkforcomodification (); parent.removerange (parentoffset + fromindex, parentoffset + toindex); this.modcount = parent.modcount; this.size- = toindex- FromIndex; } public boolean addall (collection <? extends e> c) {return addall (this.size, c); } public boolean addall (int index, collection <? extends e> c) {rangecheckforadd (index); int csize = c.size (); if (csize == 0) false를 반환합니다. CheckforComodification (); parent.addall (parentoffset + index, c); this.modcount = parent.modcount; this.size += csize; 진실을 반환하십시오. } public iterator <e> iterator () {return listiterator (); } public listiterator <e> listiterator (Final Int Index) {checkforcomodification (); rangecheckforadd (색인); 최종 int 오프셋 = this.offset; 새 Listiterator <e> () {int cursor = index를 반환합니다. int lastret = -1; int exclingModCount = arrayList.this.ModCount; public boolean hasnext () {return cursor! = Sublist.this.size; } @SuppressWarnings ( "선택 취소") public e next () {checkforcomodification (); int i = 커서; if (i> = Sublist.this.size) 새 nosuchelementException (); Object [] ElementData = ArrayList.this.elementData; if (offset + i> = ElementData.length) 새 ConcurrentModificationException (); 커서 = i + 1; return (e) ElementData [오프셋 + (lastret = i)]; } public boolean hasprevious () {return cursor! = 0; } @SuppressWarnings ( "확인되지 않은") public e previous () {checkforcomodification (); int i = 커서 -1; if (i <0) 새 nosuchelementException ()을 던지십시오. Object [] ElementData = ArrayList.this.elementData; if (offset + i> = ElementData.length) 새 ConcurrentModificationException (); 커서 = i; return (e) ElementData [오프셋 + (lastret = i)]; } @SuppressWarnings ( "확인되지 않은") 공개 void foreachRemaining (소비자 <? super e> 소비자) {objects.requirenonnull (소비자); 최종 int size = subrist.this.size; int i = 커서; if (i> = size) {return; } final object [] elementData = arrayList.this.elementData; if (offset + i> = elementData.length) {새 동시 동의 modificationException (); } while (i! = size && modcount == expectModCount) {소비자 .accept ((e) elementData [offset+(i ++)]); } // 힙 쓰기 트래픽 Lastret = cursor = i; CheckforComodification (); } public int nextIndex () {return cursor; } public int previousIndex () {return cursor -1; } public void remove remove () {if (lastret <0) 던지기 새로운 불법 스테이트 exception (); CheckforComodification (); try {subrist.this.remove (lastret); 커서 = lastret; lastret = -1; 예상 modCount = arrayList.this.ModCount; } catch (indexOutOfBoundSexception ex) {throw new concurrentModificationException (); }} public void set (e e) {if (lastret <0) 새로운 불법 스테이트 exception () 던지기; CheckforComodification (); try {arraylist.this.set (오프셋 + lastret, e); } catch (indexOutOfBoundSexception ex) {throw new concurrentModificationException (); }} public void add (e e) {checkforcomodification (); {int i = 커서; Subrist.this.add (i, e); 커서 = i + 1; lastret = -1; 예상 modCount = arrayList.this.ModCount; } catch (indexOutOfBoundSexception ex) {throw new concurrentModificationException (); }} 최종 무효 checkforcomodification () {if (exceptModCount! = arrayList.this.ModCount) 던지기 새로운 concurrentModificationException (); }}; } public list <e> subrist (int fromIndex, int toIndex) {subStrangeCheck (FromIndex, toIndex, size); 새로운 Subrist를 반환합니다 (이것은 index, toindex에서 오프셋); } private void rangeCheck (int index) {if (index <0 || index> = this.size) 새 indexOutOfBoundSexception (OutOfBoundSmsg (index)); } private void rangecheckforadd (int index) {if (index <0 || index> this.size) 새 indexOutOfBoundSexception (OutOfBoundSmsg (index)); } private String outOfBoundsmsg (int index) {return "index :"+index+", size :"+this.size; } private void checkforComodification () {if (arrayList.this.ModCount! = this.ModCount) 던지기 새로운 concurrentModificationException (); } public spliterator <e> splitterator () {checkforcomodification (); 새로운 ArrayListSpliterator <e> (ArrayList.this, Offset, Offset + this.Size, this.ModCount)를 반환합니다. }} @override public void foreach (소비자 <? super e> action) {objects.requirenonnull (action); 최종 int exclingModCount = modCount; @SuppressWarnings ( "확인되지 않은") Final e [] elementData = (e []) this.elementData; 최종 int size = this.size; for (int i = 0; modcount == excliteModCount && i <size; i ++) {action.accept (elementData [i]); } if (modCount! = excliteModCount) {새 동시 동의 modificationException (); }}/** *이 목록의 요소를 통해 <em> <a href = "spliterator.html#binding"rel = "external nofollow"> late-binding </a> </em> * 및 <em> file-binding </a> </em> * {@link spliterator}를 만듭니다. * * <p> {@code spliterator} reports {@link spliterator#size}, * {@link spliterator#subsized} 및 {@link spliterator#ordered}. * 구현을 무시하면 추가 * 특성 값의보고를 문서화해야합니다. * * * @return a {@code spliterator}이 목록의 요소에 대한 * @ceint */ @override public spliterator <e> splitterator () {return new arraylistspliterator <> (this, 0, -1, 0); } /** 인덱스 기반 분할 2, 게으른 초기화 된 스플 라이트 레이터 * /정적 최종 클래스 ArrayListSpliterator <e> Spliterator <e> { / * * ArrayList가 불변하거나 구조적으로 불변 (없음 * 추가, 제거 등)이라면 스플리터 레이터를 구현할 수 있습니다. 대신 우리는 많은 성능을 희생하지 않고 실용적으로 횡단하는 동안 많은 * 간섭을 감지합니다. 우리는 주로 * modcounts에 의존합니다. 이들은 동시성 * 폭력을 감지하는 것이 보장되지 않으며 때로는 * 스레드 내 간섭에 대해 지나치게 보수적이지만 실제로는 가치가있는 충분한 문제를 감지합니다. 이를 수행하기 위해, 우리는 (1) Lazily * 우리가 확인하고있는 주에 커밋 해야하는 최신 * 지점까지 울타리를 초기화하고 예상되는 modcount; 따라서 정밀도를 향상시킵니다. (이것은 * Subrists에 적용되지 않으며, 현재가 아닌 * 값을 가진 스플리터 어를 생성합니다). (2) 우리는 Foreach * (가장 성능에 민감한 방법)의 끝에서 단일 * ConcurrentModificationException 검사 만 수행합니다. Foreach *를 사용하는 경우 (반복자와 반대로) 일반적으로 이전이 아닌 작업 후 * 간섭 만 감지 할 수 있습니다. 추가 * CME 트리거 점검은 다른 모든 가능한 가정 폭력에 적용됩니다. 이를 통해 Foreach의 내부 루프 *는 추가 점검없이 실행할 수 있으며 * 람다 해상도를 단순화합니다. 이것은 * 수표 수를 수반하지만 * list.stream (). foreach (a)의 공동 사례에서는 수표 나 다른 컴퓨팅 *이없는 곳에서는 다른 곳에서 발생하지 않습니다. 다른 * 덜 사용되지 않은 방법은 이러한 간소화의 대부분을 활용할 수 없습니다. */ Private Final ArrayList <E> 목록; 개인 INT 인덱스; // 사전/분할 개인 int 펜스에서 수정 된 현재 색인; // -1이 사용될 때까지; 그런 다음 과거의 마지막 인덱스 Private int expectModCount; // 펜스 세트시 초기화/ ** 주어진 범위를 덮는 새 스플 라이트 레이터를 만듭니다*/ arraylistspliterator (arraylist <e> 목록, int origin, int fence, int exploymodcount) {this.list = list; // null이 null이 횡단되지 않는 한 null 인 경우 Ok.index = origin; this.fence = 울타리; this.expectedModCount = exclingModCount; } private int getfence () {// int hi를 먼저 사용하기 위해 울타리를 초기화합니다. // (Specialized Variant가 Method foreach에 나타납니다) ArrayList <e> lst; if ((hi = fence) <0) {if ((lst = list) == null) hi = fence = 0; else {expostModCount = lst.ModCount; hi = fence = lst.size; }} return hi; } public arraylistSpliterator <e> trysplit () {int hi = getfence (), lo = index, mid = (lo + hi) >>> 1; return (lo> = mid)? NULL : // 너무 작은 새 ArrayListSpliterator <e>가 아니라면 범위를 반으로 나눕니다 (list, lo, index = mid, exportModCount); } public boolean tryAdvance(Consumer<? super E> action) { if (action == null) throw new NullPointerException(); int hi = getFence(), i = index; if (i < hi) { index = i + 1; @SuppressWarnings("unchecked") E e = (E)list.elementData[i]; action.accept(e); if (list.modCount != expectedModCount) throw new ConcurrentModificationException(); 진실을 반환하십시오. } false를 반환합니다. } public void forEachRemaining(Consumer<? super E> action) { int i, hi, mc; // hoist accesses and checks from loop ArrayList<E> lst; Object[] a; if (action == null) throw new NullPointerException(); if ((lst = list) != null && (a = lst.elementData) != null) { if ((hi = fence) < 0) { mc = lst.modCount; hi = lst.size; } else mc = expectedModCount; if ((i = index) >= 0 && (index = hi) <= a.length) { for (; i < hi; ++i) { @SuppressWarnings("unchecked") E e = (E) a[i]; action.accept(e); } if (lst.modCount == mc) return; } } throw new ConcurrentModificationException(); } public long estimateSize() { return (long) (getFence() - index); } public int characteristics() { return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED; } } @Override public boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); // figure out which elements are to be removed // any exception thrown from the filter predicted at this stage // will leave the collection unmodified int removeCount = 0; final BitSet removeSet = new BitSet(size); final int expectedModCount = modCount; final int size = this.size; for (int i=0; modCount == expectedModCount && i < size; i++) { @SuppressWarnings("unchecked") final E element = (E) elementData[i]; if (filter.test(element)) { removeSet.set(i); removeCount++; } } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } // shift surviving elements left over the spaces left by removed elements final boolean anyToRemove = removeCount > 0; if (anyToRemove) { final int newSize = size - removeCount; for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) { i = removeSet.nextClearBit(i); elementData[j] = elementData[i]; } for (int k=newSize; k < size; k++) { elementData[k] = null; // Let gc do its work } this.size = newSize; if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; } return anyToRemove; } @Override @SuppressWarnings("unchecked") public void replaceAll(UnaryOperator<E> operator) { Objects.requireNonNull(operator); final int expectedModCount = modCount; final int size = this.size; for (int i=0; modCount == expectedModCount && i < size; i++) { elementData[i] = operator.apply((E) elementData[i]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; } @Override @SuppressWarnings("unchecked") public void sort(Comparator<? super E> c) { final int expectedModCount = modCount; Arrays.sort((E[]) elementData, 0, size, c); if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; }}요약
The above is all about ArrayList source code analysis in Java programming, and I hope it will be helpful to everyone. 관심있는 친구는이 사이트의 다른 관련 주제를 계속 참조 할 수 있습니다. 단점이 있으면 메시지를 남겨 두십시오. 이 사이트를 지원해 주신 친구들에게 감사드립니다!