시그마 삽질==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