기록창고

JAVA List for 문으로 remove하기 본문

JAVA

JAVA List for 문으로 remove하기

방금시작한사람 2020. 1. 5. 23:16

List 에 있는 목록 중 원하는 객체를 삭제하는 방법.

 

맨 처음에는 가장 간단하게 for문으로 돌리면서 찾아서 삭제를 했다.

import java.util.*;

public class test {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        list.add("A");
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("D");
        list.add("E");

        for(int i=0;i<list.size();i++){
            String str = list.get(i);
            if(str.equals("A")) list.remove(i);
        }
        System.out.println(String.join(", ", list));
    }
}

위 코드는 list 중 "A"랑 같은게 있으면 삭제해라는 코드이다.
그치만 실제로 출력 결과를 보면 A, B, C, D, E 가 출력된다.

 

이유는 첫번째 A가 삭제되면서 두번째 A의 인덱스로 1에서 0으로 변경되었기 때문이다..


A A B C D E -> A B C D E
0 1 2 3  4 5 -> 0 1  2 3 4

이렇게 변경되어, i 는 1로 변경된다. 그래서 두번째 A는 발견되지 않고 삭제가 되지 않는다.

        for(int i=0;i<list.size();i++){
            String str = list.get(i);
            if(str.equals("A")) list.remove(i--); // i -> i--
        }
        // B, C, D, E;

그래서 if문에 걸려 remove가 되면 i를 하나빼서 그 자리부터 다시 돌게 하는 방법도 있다.
이 방법은 왠지 별로 같다..

 

왜냐하면 아래 만약 i를 가지고 수행하는 로직이 있다면, i-1 값으로 생각하고 코드를 작성해야하기 때문에
불편하고 가독성이 떨어질 거 같다. 그래도 위의 코드에서는 원하는 바를 달성한다.

 

 

다른 방법은 iterator를 이용하는 법이다.

        for(Iterator<String> it=list.iterator(); it.hasNext();){
            String str = it.next();
            if(str.equals("A")) it.remove();
        }

index를 이용한 for문과 비슷해보인다.

왜 it.remove()를 해도 잘 작동이 될까?

아래 Iterator의 remove 함수 와 next 함수이다.

    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();
        }
    }
    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];
        // 삭제되어 lastRet이 -1로 되지않으면, cursor와 lastRet는 1차이 밖에 나지않는다.
    }

lastRet 은 마지막으로 리턴한 값의 인덱스이다.
cursor 는 다음에 리턴될 값의 인덱스이다.

 

그래서 remove 함수는 마지막으로 리턴한 값의 인덱스를 지워버리고
현재 커서를 다시 그곳으로 옮겨놓는다.

 

첫번째 A
it.next() 이후, cursor = 1, lastRet = 0;
it.remove() 이후, 첫번째 A는 사라지고 다시 커서는 0 으로 바꾸고, lastRet은 -1로 바꾼다.

 

두번째 A
it.next() 이후, cursor = 1, lastRet = 0;
it.remove() 이후는 위와 같은 동작을 한다.

 

마치 코드가 for 문을 index에서 수정한것 처럼 커서를 -1 해준다.

 

까보니 잘 모르겠다....

 

iterator를 쓴것과 안쓴것의 차이를..

 

가독성이 좋고 .... 흠.. 모르겠다.

 

 

추가로 Collection 을 이용하는 방법도 있다.
JAVA 8 부터 지원한다고 한다.

    list.removeIf(str -> str.equals("A"));
    System.out.println(String.join(", ", list));

매우 많이 간단해졌따... 헣;;


코드도 처음보는 사람도 읽기 쉽다.

 

만약 아래와 같은 조건이 만족한다면 지워라 라고 코드에 서술해 놓은거 같다.
깔끔하게 이쁘다.

 

끝!

'JAVA' 카테고리의 다른 글

String.equals()  (0) 2020.01.19
Collectors GroupingBy  (0) 2020.01.16
equals() override  (0) 2019.12.28
hashCode() override  (0) 2019.12.27
static 에 관하여  (0) 2019.12.22
Comments