시그마 삽질==six 시그마

자바 반복문 도중 배열 삭제(ConcurrentModificationException) 본문

프로그래밍/Java

자바 반복문 도중 배열 삭제(ConcurrentModificationException)

Ethan Matthew Hunt 2020. 3. 22. 10:14

1. 향상된 for문중에 삭제

 

	public static void main(String[] args) {

		List<String> list = new ArrayList<String>();

		list.add("장동건");
		list.add("이동욱");
		list.add("원빈");
		list.add("하정우");
		list.add("정우성");
		list.add("이민호");

		for (String str: list) {
			if(str.equals("원빈")|| str.equals("하정우")) {
				list.remove(str);
			}
		}
		System.out.println(list); 

	}

 

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at com.atomy.seminar.web.admin.ThreadTest.main(ThreadTest.java:33)

 

에러가 발생한 이유는 순회하는 동안 Collection이 변경되면  ConcurrentModificationException을 발생시키기 때문이다.

 

자세한 원인 참조

 

 

 

2. for문 도중에 삭제

 

public static void main(String[] args) {

		List<String> list = new ArrayList<String>();

		list.add("장동건");
		list.add("이동욱");
		list.add("원빈");
		list.add("하정우");
		list.add("정우성");
		list.add("이민호");
		
		for (int i = 0; i < list.size(); i++) {
			if(list.get(i).equals("원빈")|| list.get(i).equals("하정우")) {
				list.remove(i);
			}
		}
		
		System.out.println(list); 

	}

 

결과는 어떻게 될까???

 

 

[장동건, 이동욱, 하정우, 정우성, 이민호]

 

하정우가 살아있다 ㅎ 

 

이유는 i가 2일때 list.get(2)는 원빈이었는데 원빈이 삭제된후 

 

list가 왼쪽으로 한칸씩 이동하여 

 

i가 3인 list.get(3)은 하정우가 아닌 정우성이 되었기때문에 하정우는 패스된 것이다.

 

 

 

3. iterator 사용시

 

	public static void main(String[] args) {

		List<String> list = new ArrayList<String>();

		list.add("장동건");
		list.add("이동욱");
		list.add("원빈");
		list.add("하정우");
		list.add("정우성");
		list.add("이민호");

		for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) {
			String str = iter.next();
			if(str.equals("원빈")|| str.equals("하정우")) {
				iter.remove();
			}
		}
        
		System.out.println(list); 

	}

 

결과는? 

 

[장동건, 이동욱, 정우성, 이민호]

list.remove(str)이 아니고 iter.remove() 를 써야됨

 

자바 공식 튜토리얼에 따르면 iterator는 iteration중 콜랙션을 삭제할때 가장 safe한 방법이라고 나와있다. 요기 참조

 

 

 

4 중첩 Iterator 삭제

 

 

Iterator<Data1> d1 = list1.iterator();
while( d1.hasNext()) {
	Data1 dd1=d1.next();
	Iterator<Data2> d2 = list2.iterator();
	while( d2.hasNext()) {
		Data2 dd2=d2.next();
		if(dd1.getName().equals(dd2.getName())) {
			d2.remove();
		}
	}
}

 

 

5. Java 8 removeIf 사용시

 

	public static void main(String[] args) {

		List<String> list = new ArrayList<String>();

		list.add("장동건");
		list.add("이동욱");
		list.add("원빈");
		list.add("하정우");
		list.add("정우성");
		list.add("이민호");
		
		list.removeIf(v->v.equals("원빈") || v.equals("하정우"));

		System.out.println(list); 

	}

 

[장동건, 이동욱, 정우성, 이민호]

 

 

6. 이런방법도 있긴하다

 

List<Person> data=list.stream().filter(v->{
			boolean result=false;
			for (Car c:v.getCarList()) {
				if(c.getName().equals("소나타")){
					result= true;
					break;
				}
			}
			return result;
		}).collect(Collectors.toList());

 

7. 똑같은 배열 하나 더 만들어서 제외시킬수도 있다..(clone or whatever.. index usable)

Comments