소 백 일기[List 반복 삭제]
5612 단어 소 백 일기
소 백 오늘 퀘 스 트:List 교체 중 요소 삭제
1.소 백 사고:교체 기 를 사용 하여 실현
1)테스트 소스 코드:
private List rookieList;
@BeforeEach
public void initList() {
//
rookieList = new ArrayList(){{
add(" ");
add(" ");
add(" ");
add(" ");
}};
}
@Test
public void removeItem() {
//
Iterator rookieIterator = rookieList.iterator();
//
while (rookieIterator.hasNext()) {
String item = rookieIterator.next();
if(item.equals(" ")) {
rookieIterator.remove();
System.out.println(item +" , ");
}
}
//
System.out.println(" :");
rookieList.forEach(System.out::println);
}
2)결과 인쇄:
,
:
2.소 백 탐색:원생 List remove 방법 을 이용 하여 왜 Concurrent ModificationException 이상 이 발생 합 니까?
1)테스트 소스 코드:
@Test
public void removeItemByList() {
for(String item:rookieList) {
if(item.equals(" ")) {
rookieList.remove(item);
System.out.println(item +" , ");
}
}
//
System.out.println(" :");
rookieList.forEach(System.out::println);
}
2)결과 인쇄:
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at com.wd.IterateTest.removeItemByList(IterateTest.java:27)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at java.util.ArrayList.forEach(ArrayList.java:1257)
3)잘못된 점 찾기:
// ArrayList:849
int expectedModCount = modCount;
// ArrayList:858-868
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];
}
// ArrayList:907-910
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException(); //
}
Concurrent ModificationException 이 반복 요소 검사 시 modCount != expected ModCount 가 촉발 합 니 다.그러면 modCount 와 expected ModCount 는 각각 무슨 뜻 을 의미 합 니까?의문 을 가지 고 코드 와 관련 자 료 를 뒤 져 보기 시작 했다.
modCount:
,modCount , add remove
expectedModCount:
, , ,
modCount ,
: ArrayList ,
, remove , remove
remove 소스 코드 및 관련 방법 찾기
//ArrayList:523-538
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;
}
//ArrayList:544-551
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
}
코드 를 통 해 reove 방법 이 실제 적 으로 fast Remove 방법 을 호출 한 것 을 볼 수 있 습 니 다.fast Remove 에서 우리 가 관심 을 가 지 는 modCount 에 대해 우리 가 예상 하 는 추가 작업 을 했 습 니 다.그러나 이것 은 다른 관련 값 expected ModCount 의 조작 을 보지 못 했 습 니 다.즉,modCount 는 reove 후에 1 로 변 했 지만 expected ModCount 는 초기 화 된 0 입 니 다.다음 교체 시 이들 은 같 지 않 습 니 다.이상 을 던지다
4)의외로 마지막 두 번 째 요 소 를 삭제 할 때 정상적으로 작 동 하 는 것 을 발견 했다?
코드 와 자 료 를 오랫동안 찾 아 보고 개인 이 이해 하 는 원인,핵심 코드 를 찾 았 습 니 다.
//ArrayList:853:855
public boolean hasNext() {
return cursor != size;
}
cursor 는 현재 교체 되 는 위 치 를 말 합 니 다.size 는 현재 집합 크기 를 말 합 니 다.hasNext 방법 은 집합 하여 교체 가 완료 되 었 는 지 여 부 를 판단 하 는 표지 입 니 다.이 방법 은 우리 가 이미 잘 알 고 있 습 니 다.마지막 두 번 째 요 소 를 삭제 할 때, cursor 는 length-1 의 위 치 를 가리 키 고 하나의 요 소 를 삭제 한 집합 size 도 length-1 이다.우연 한 일치 로 교체 종 료 를 추진 하여 삭제 에 성공 한 가상 이 생 겼 다.
5)왜 Iterator 가 정상적으로 작 동 합 니까?
같은 방법 으로 Iterator 의 reove 방법 을 찾 습 니 다:
//ArrayList:870-883
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();
}
}
핵심 한 마디 발견:expected ModCount=modCount
이로써 샤 오 백 은 오늘 임 무 를 완수 했다^^