java.util을 피하는 방법동시 수정Array List에서 요소를 삭제하고 반복할 때의 예외
어레이 리스트반복하면서 동시에 요소를 제거해야 합니다.은 분명히 「 」를 던진다.java.util.ConcurrentModificationException
.
이 문제에 대처하기 위한 베스트 프랙티스는 무엇입니까?먼저 목록을 복제해야 합니까?
루프 자체에 있는 요소가 아니라 코드의 다른 부분을 제거합니다.
코드는 다음과 같습니다.
public class Test() {
private ArrayList<A> abc = new ArrayList<A>();
public void doStuff() {
for (A a : abc)
a.doSomething();
}
public void removeA(A a) {
abc.remove(a);
}
}
a.doSomething
라고 좋다Test.removeA()
;
두 가지 옵션:
- 삭제할 값 목록을 만들고 루프 내의 목록에 추가한 후 호출합니다.
originalList.removeAll(valuesToRemove)
- 하다를 사용하세요.
remove()
메서드를 사용합니다.이는 확장 for 루프를 사용할 수 없음을 의미합니다.
두 번째 옵션의 예로서 길이가5보다 큰 문자열을 목록에서 삭제합니다.
List<String> list = new ArrayList<String>();
...
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String value = iterator.next();
if (value.length() > 5) {
iterator.remove();
}
}
ArrayList의 JavaDocs에서
이 클래스의 반복자 및 listIterator 메서드에 의해 반환되는 반복자는 fail-fast입니다.반복자 자신의 삭제 또는 추가 메서드를 제외한 어떤 방법으로든 목록이 구조적으로 변경되면 반복자는 Concurrent Modification을 슬로우합니다.예외.
고급 "for loop"의 목록에서 값을 제거하려고 합니다. 이는 코드 내에서 수행한 트릭을 적용하더라도 가능하지 않습니다.여기서 권장하는 다른 방법으로 반복기 레벨을 코드화하는 것이 좋습니다.
나는 사람들이 어떻게 전통적인 루프 접근법을 제안하지 않았는지 궁금하다.
for( int i = 0; i < lStringList.size(); i++ )
{
String lValue = lStringList.get( i );
if(lValue.equals("_Not_Required"))
{
lStringList.remove(lValue);
i--;
}
}
이것도 돼요.
Java 8에서는 수집 인터페이스를 사용하여 removeIf 메서드를 호출하여 이를 수행할 수 있습니다.
yourList.removeIf((A a) -> a.value == 2);
자세한 내용은 이쪽
기존 방식으로 어레이를 반복하기만 하면 됩니다.
목록에서 요소를 제거할 때마다 이후의 요소가 앞으로 푸시됩니다.반복 요소 이외의 요소를 변경하지 않는 한 다음 코드가 작동합니다.
public class Test(){
private ArrayList<A> abc = new ArrayList<A>();
public void doStuff(){
for(int i = (abc.size() - 1); i >= 0; i--)
abc.get(i).doSomething();
}
public void removeA(A a){
abc.remove(a);
}
}
목록을 반복하는 동안 요소를 제거할 수 있습니다.아래에 예를 제시하겠습니다.
ArrayList<String> names = new ArrayList<String>();
names.add("abc");
names.add("def");
names.add("ghi");
names.add("xyz");
상기 어레이 리스트의 이름을 가지고 있습니다.그리고 위의 목록에서 "def" 이름을 삭제하고 싶습니다.
for(String name : names){
if(name.equals("def")){
names.remove("def");
}
}
위의 코드는 Concurrent Modification을 슬로우합니다.반복하는 동안 목록을 수정하기 때문에 예외입니다.
이렇게 함으로써 어레이 목록에서 "def" 이름을 삭제하려면
Iterator<String> itr = names.iterator();
while(itr.hasNext()){
String name = itr.next();
if(name.equals("def")){
itr.remove();
}
}
위의 코드를 반복하여 어레이 목록에서 "def" 이름을 삭제하고 어레이를 인쇄하면 다음 출력이 나타납니다.
출력 : [abc, ghi, xyz]
는 정상적인으로 합니다.java.util.ConcurrentModificationException
는 액세스되는 요소와 관련된 오류입니다.
시험해 보세요.
for(int i = 0; i < list.size(); i++){
lista.get(i).action();
}
다음은 다른 목록을 사용하여 제거할 개체를 추가한 다음 스트림을 사용하는 예입니다.원래 목록에서 요소를 제거하려면 foreach:
private ObservableList<CustomerTableEntry> customersTableViewItems = FXCollections.observableArrayList();
...
private void removeOutdatedRowsElementsFromCustomerView()
{
ObjectProperty<TimeStamp> currentTimestamp = new SimpleObjectProperty<>(TimeStamp.getCurrentTime());
long diff;
long diffSeconds;
List<Object> objectsToRemove = new ArrayList<>();
for(CustomerTableEntry item: customersTableViewItems) {
diff = currentTimestamp.getValue().getTime() - item.timestamp.getValue().getTime();
diffSeconds = diff / 1000 % 60;
if(diffSeconds > 10) {
// Element has been idle for too long, meaning no communication, hence remove it
System.out.printf("- Idle element [%s] - will be removed\n", item.getUserName());
objectsToRemove.add(item);
}
}
objectsToRemove.stream().forEach(o -> customersTableViewItems.remove(o));
}
가지 은 1을 입니다.removeA
-method에 메서드 -
public void removeA(A a,Iterator<A> iterator) {
iterator.remove(a);
}
의 ★★★★★★★★★★★★★★★★★★★★★★★★★★★.doSomething()
할 수 iterator
remove
생각이 아니에요.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
이 작업을 2단계로 수행할 수 있습니까?목록에서 반복할 때 첫 번째 루프에서는 선택한 요소를 삭제하는 대신 삭제 마크를 붙입니다.이 경우는, 이러한 요소(얇은 카피)를 다른 요소에 카피하는 것만으로 끝납니다.List
.
이 끝나면 그냥 , 하다, 하다, 하다, 하다, 하다, 하면 요.removeAll
첫 번째 목록에서 두 번째 목록의 모든 요소를 선택합니다.
내 경우, 수락된 답변이 작동하지 않습니다. 예외는 중지되지만 목록에 불일치가 발생합니다.다음과 같은 해결책이 나에게 완벽하게 효과가 있다.
List<String> list = new ArrayList<>();
List<String> itemsToRemove = new ArrayList<>();
for (String value: list) {
if (value.length() > 5) { // your condition
itemsToRemove.add(value);
}
}
list.removeAll(itemsToRemove);
삭제할 하고, 그 에 이 in in른 、 이른 、 이른 、 이른 、 이 in 른 in in 、 in in 、 in in 、 。list.removeAll
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
각 루프에 대해 For를 사용하는 대신 normal for loop을 사용합니다.예를 들어, 다음 코드는 java.display를 지정하지 않고 배열 목록 내의 모든 요소를 삭제합니다.동시 수정예외.사용 사례에 따라 루프 내의 조건을 변경할 수 있습니다.
for(int i=0; i<abc.size(); i++) {
e.remove(i);
}
다음과 같이 간단한 작업을 수행합니다.
for (Object object: (ArrayList<String>) list.clone()) {
list.remove(object);
}
스트림을 사용하는 대체 Java 8 솔루션:
theList = theList.stream()
.filter(element -> !shouldBeRemoved(element))
.collect(Collectors.toList());
Java 7에서는 Guava를 대신 사용할 수 있습니다.
theList = FluentIterable.from(theList)
.filter(new Predicate<String>() {
@Override
public boolean apply(String element) {
return !shouldBeRemoved(element);
}
})
.toImmutableList();
Guava의 예에서는 원하는 목록과 그렇지 않은 목록이 나타납니다.
ArrayList 대신 CopyOnWriteArrayList를 사용할 수도 있습니다.이것은 JDK 1.5 이후가 권장하는 최신 접근법입니다.
for (A a : new ArrayList<>(abc)) {
a.doSomething();
abc.remove(a);
}
가끔은 구식이 최고일 때도 있어요.단순한 for 루프를 사용하지만 그렇지 않으면 항목을 제거할 때 인덱스와 동기화되지 않습니다.
List<String> list = new ArrayList<>();
for (int i = list.size() - 1; i >= 0; i--) {
if ("removeMe".equals(list.get(i))) {
list.remove(i);
}
}
"먼저 목록을 복제해야 할까요?"
이것이 가장 쉬운 해결책입니다.클론에서 삭제하고 삭제 후 클론을 다시 복사합니다.
내 럼미컵 게임의 예:
SuppressWarnings("unchecked")
public void removeStones() {
ArrayList<Stone> clone = (ArrayList<Stone>) stones.clone();
// remove the stones moved to the table
for (Stone stone : stones) {
if (stone.isOnTable()) {
clone.remove(stone);
}
}
stones = (ArrayList<Stone>) clone.clone();
sortStones();
}
늦었지만 이 솔루션은 심플하고 우아하다고 생각하기 때문에 이 답변을 드렸습니다.
List<String> listFixed = new ArrayList<String>();
List<String> dynamicList = new ArrayList<String>();
public void fillingList() {
listFixed.add("Andrea");
listFixed.add("Susana");
listFixed.add("Oscar");
listFixed.add("Valeria");
listFixed.add("Kathy");
listFixed.add("Laura");
listFixed.add("Ana");
listFixed.add("Becker");
listFixed.add("Abraham");
dynamicList.addAll(listFixed);
}
public void updatingListFixed() {
for (String newList : dynamicList) {
if (!listFixed.contains(newList)) {
listFixed.add(newList);
}
}
//this is for add elements if you want eraser also
String removeRegister="";
for (String fixedList : listFixed) {
if (!dynamicList.contains(fixedList)) {
removeResgister = fixedList;
}
}
fixedList.remove(removeRegister);
}
이 모든 것은 한 목록에서 다른 목록으로 업데이트하기 위한 것입니다.단 하나의 목록에서 모든 것을 만들 수 있습니다.메서드 업데이트에서는 두 목록을 모두 체크하고 요소들을 지우거나 추가할 수 있습니다.즉, 양쪽 리스트는 항상 같은 사이즈입니다.
어레이 목록 대신 반복기 사용
유형이 일치하는 반복기로 변환되도록 설정
그리고 다음 요소로 이동하여
Iterator<Insured> itr = insuredSet.iterator();
while (itr.hasNext()) {
itr.next();
itr.remove();
}
요소를 제거하기 위해 인덱스를 사용해야 하므로 다음 항목으로 이동하는 것이 중요합니다.
목록에서 모든 요소를 제거하는 것이 목표인 경우 각 항목에 대해 반복한 후 다음을 호출할 수 있습니다.
list.clear()
의 경우는?
import java.util.Collections;
List<A> abc = Collections.synchronizedList(new ArrayList<>());
에러
요소를 가져온 동일한 목록에 추가할 때 오류가 발생했습니다.
fun <T> MutableList<T>.mathList(_fun: (T) -> T): MutableList<T> {
for (i in this) {
this.add(_fun(i)) <--- ERROR
}
return this <--- ERROR
}
결정
새 목록에 추가할 때 잘 작동합니다.
fun <T> MutableList<T>.mathList(_fun: (T) -> T): MutableList<T> {
val newList = mutableListOf<T>() <--- DECISION
for (i in this) {
newList.add(_fun(i)) <--- DECISION
}
return newList <--- DECISION
}
ArrayList.remove(A) 스테이트먼트 뒤에 쉼표를 추가합니다.
언급URL : https://stackoverflow.com/questions/8104692/how-to-avoid-java-util-concurrentmodificationexception-when-iterating-through-an
'programing' 카테고리의 다른 글
C의 롤링 중위수 알고리즘 (0) | 2022.08.25 |
---|---|
@vue/cli-plugin-unit-mocha, TypeScript 및 SFC를 사용한 VueJ 프로젝트의 NYC 커버리지 보고서 생성 (0) | 2022.08.25 |
vue.display 내의 foreach 루프에서 액세스 변수 (0) | 2022.08.25 |
VUEJS의 URL에서 ID 가져오기 (0) | 2022.08.25 |
Java에서 한 디렉토리에서 다른 디렉토리로 파일 복사 (0) | 2022.08.25 |