자바 집합 ArrayList 에서 modCount 상세 설명 및 subList 함수 요점
11468 단어 자바 개발
이른바 Concurrent ModificationException 을 번역 하면 수정 이상 이 동시에 발생 하 는 것 입 니 다.인터넷 에서 이 이상 이 발생 하 는 원인 은 대부분 교체 기 를 사용 할 때 발생 합 니 다.예 를 들 어:
import java.util.ArrayList;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
ArrayList array = new ArrayList();
//
array.add("hello");
array.add("world");
array.add("java");
Iterator it = array.iterator();
while (it.hasNext()) {
String s = (String) it.next();
if ("world".equals(s)) {
array.add("javaee");
}
}
}
}
이 예 에서 우 리 는 교체 기 를 사용 하여 교체 하 는 과정 에서 집합 을 조작(이곳 의 추가 작업 에 국한 되 지 않 고 삭제 등 일 수도 있 음)하여 교체 기 가 효력 을 잃 고 이 이상 을 던 졌 다.그러나 프로젝트 에서 본인 은 교체 기 를 사용 하지 않 고 다음 코드 가 존재 합 니 다.
List tableEntities = tableData.getValue().subList(1, tableData.getValue().size());
List newEntitys = tableData.getValue().subList(0,1);
List entities = sortTableEntity(tableEntities);
newEntitys.addAll(entities);
tableData.getValue().clear();
tableData.getValue().addAll(newEntitys);
이상 하 게 마지막 단계 에 던 져.이 를 통 해 알 수 있 듯 이 Concurrent ModificationException 이상 은 교체 기 를 사용 할 때 만 나타 나 는 것 이 아니다.Array List 류 의 subList 소스 코드 를 분석 하면 알 수 있 습 니 다.
public List subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
여기에서 SubList 의 대상 을 되 돌려 주 었 고 그 구조 함수 내부 에서
SubList(AbstractList 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;
}
this.modCount=Array List.this.modCount 라 는 코드 를 볼 수 있 습 니 다.첫 번 째 교체 기의 예 에서 iterator()함 수 를 통 해 되 돌아 오 는 교체 기 는 구조 에서 도 사용 되 었 다.
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
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];
}
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();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
이 이상 한 던 지기 가 modCount 와 관련 이 있 고 modCount 속성 은 AbstractList 추상 류 에서 계승 되 었 음 을 알 수 있 습 니 다.javadoc 문서 의 설명 보기:
The number of times this list has been structurally modified. Structural modifications are those that change the size of the list, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results. This field is used by the iterator and list iterator implementation returned by the iterator and listIterator methods. If the value of this field changes unexpectedly, the iterator (or list iterator) will throw a ConcurrentModificationException in response to the next, remove, previous, set or add operations. This provides fail-fast behavior, rather than non-deterministic behavior in the face of concurrent modification during iteration.
우 리 는 이 매개 변 수 는 집합 이 수 정 된 횟수 를 기록 하 는 데 사용 되 는 것 을 알 고 있 습 니 다.수 정 된 횟수 를 기록 하려 는 이 유 는 ArrayList 가 스 레 드 가 안전 하지 않 기 때 문 입 니 다.교체 기와 서브 시퀀스 를 사용 하 는 과정 에서 원 집합 에 대한 수정 으로 인해 교체 기와 서브 시퀀스 의 실 효 를 방지 하기 위해 수정 횟수 의 기록 을 저 장 했 습 니 다.교체 기의 조작 과 서브 시퀀스 의 조작 과정 에서먼저 modCount 가 같은 지(함수 check ForComodification())를 확인 하고 기다 리 지 않 으 려 면 집합 이 수정 되 었 다 는 것 을 설명 한다.그러면 후속 적 으로 명확 하지 않 은 오류 가 발생 하지 않도록 이 이상 을 던 졌 다.이 이상 을 방지 하기 위해 서 는 교체 기 를 사용 하여 집합 을 하 는 교체 가 집합 을 수정 하려 면 교체 기 가 제공 하 는 집합 을 조작 하 는 함수 로 이 루어 져 야 한다.그리고 제 코드 에 나타 난 문제 에 대해 다음 과 같이 수정 할 수 있 습 니 다.
List tableEntities = Lists.newArrayList(tableData.getValue().subList(1, tableData.getValue().size()));
List newEntitys = Lists.newArrayList(tableData.getValue().subList(0,1));
List entities = sortTableEntity(tableEntities);
newEntitys.addAll(entities);
tableData.getValue().clear();
tableData.getValue().addAll(newEntitys);
이렇게 되면 뉴 엔 티 티 스 는 SubList 의 대상 이 아니 라 ArrayList 의 대상 이다.이 상황 도 처음 만 났 고 인터넷 의 다른 해석 은 기본적으로 첫 번 째 상황(즉 교체 기 사용)이 발생 했다.사실 첫 번 째 상황 이 든 두 번 째 상황 이 든 본질은 원래 집합 한 modCount 가 수정 되 어 SubList 의 modCount 나 교체 기의 expected ModCount 와 다 르 기 때문이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
자바 에서 흔히 볼 수 있 는 몇 가지 http 요청 사례위의 4 가지 방법 은 get 과 post 요청 을 보 낼 수 있 는 방법 입 니 다. 1 번: HttpURLConnection, 2 번: URLConnection, 3 번: HttpClient, 4 번 째: Soc...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.