본문 바로가기
Java/Java이론

List의 효율적인 탐색 및 수정 방법

by P_eli 2024. 11. 1.
728x90
반응형

컬렉션 프레임워크에서 리스트(List)는 데이터를 효율적으로 저장하고 접근하는 데 많이 사용됩니다. 리스트를 탐색하고 수정하는 방법에는 forEach, Iterator, ListIterator 같은 다양한 메서드가 있습니다. 이 글에서는 각각의 방법을 코드 예시와 함께 설명하고, ListIterator의 심화 개념인 양방향 탐색과 요소 추가/삭제 기능에 대해 상세히 다룹니다.

 

1. forEach를 이용한 리스트 탐색

Java 8에서 추가된 forEach 메서드는 간결하고 가독성이 좋은 코드로 리스트를 탐색하는 데 유용합니다. 내부적으로 Consumer 인터페이스를 사용해, 각 요소를 처리할 수 있습니다. 단, forEach는 단방향 탐색만 가능하며, 리스트의 크기나 구조를 수정할 수 없습니다.

코드 예시

import java.util.Arrays;
import java.util.List;

public class ForEachExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

        names.forEach(name -> {
            System.out.println("Name: " + name);
        });
    }
}

 

위 코드에서는 forEach 메서드를 사용해 리스트의 모든 요소를 출력합니다. 가독성이 좋고, 불필요한 인덱스를 사용할 필요가 없어 효율적입니다. 다만, 리스트 요소를 변경하는 작업은 불가능합니다.

 

2. Iterator를 이용한 리스트 탐색 및 수정

Iterator는 forEach보다 다양한 기능을 제공합니다. 특히, 탐색 중 요소를 삭제할 수 있는 유일한 방법입니다. Iterator는 hasNext()와 next() 메서드를 사용해 단방향으로 리스트를 탐색하며, remove() 메서드를 통해 탐색 중인 요소를 삭제할 수 있습니다.

코드 예시

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class IteratorExample {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>(Arrays.asList("Alice", "Bob", "Charlie"));
        Iterator<String> iterator = names.iterator();

        while (iterator.hasNext()) {
            String name = iterator.next();
            if ("Bob".equals(name)) {
                iterator.remove(); // "Bob" 요소 삭제
            }
        }
        System.out.println(names); // 출력 결과: [Alice, Charlie]
    }
}

위 코드에서는 Iterator를 사용해 리스트의 각 요소를 탐색하면서, 특정 조건을 만족하는 요소(이 경우, "Bob")를 삭제합니다. Iterator는 remove 메서드를 통해 ConcurrentModificationException 없이 안전하게 요소를 제거할 수 있는 장점이 있습니다.

 

3. ListIterator를 이용한 양방향 탐색 및 수정

ListIterator는 Iterator의 확장된 버전으로, 리스트를 양방향으로 탐색하고, 요소를 추가하거나 삭제할 수 있는 기능을 제공합니다. ListIterator는 hasPrevious()와 previous() 메서드를 사용해 역방향 탐색이 가능하며, add()와 remove()를 통해 리스트 요소를 수정할 수 있습니다.

코드 예시

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;

public class ListIteratorExample {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>(Arrays.asList("Alice", "Bob", "Charlie"));
        ListIterator<String> listIterator = names.listIterator();

        // 순방향 탐색 및 요소 수정
        while (listIterator.hasNext()) {
            String name = listIterator.next();
            if ("Bob".equals(name)) {
                listIterator.set("Bobby"); // "Bob"을 "Bobby"로 변경
            }
        }

        // 역방향 탐색 및 요소 추가
        while (listIterator.hasPrevious()) {
            String name = listIterator.previous();
            if ("Alice".equals(name)) {
                listIterator.add("Alex"); // "Alice" 앞에 "Alex" 추가
            }
        }
        System.out.println(names); // 출력 결과: [Alex, Alice, Bobby, Charlie]
    }
}

위 예시에서는 ListIterator를 사용하여 먼저 순방향으로 리스트를 탐색하면서 "Bob"을 "Bobby"로 수정한 후, 역방향으로 탐색하여 "Alice" 앞에 "Alex"를 추가했습니다. ListIterator는 양방향 탐색과 요소 추가/수정이 모두 가능하다는 점에서 유용합니다.

 

심화 개념: ListIterator의 양방향 탐색과 요소 추가/삭제

ListIterator는 Iterator와 달리 양방향 탐색이 가능한 점이 큰 장점입니다. next()와 previous() 메서드를 번갈아 사용할 수 있어 탐색 위치를 자유롭게 이동할 수 있습니다. 또한, set() 메서드를 통해 현재 요소를 수정할 수 있고, add() 메서드를 통해 현재 위치에 요소를 추가할 수도 있습니다.

양방향 탐색과 요소 추가/삭제

ListIterator는 add()와 remove() 메서드를 통해, 반복문 중에도 요소를 추가하거나 삭제할 수 있습니다. 하지만 add() 메서드는 요소를 현재 위치에 삽입하며, remove() 메서드는 바로 직전에 반환된 요소만 삭제할 수 있습니다.

코드 예시

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;

public class ListIteratorAdvancedExample {
    public static void main(String[] args) {
        List<String> items = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry"));
        ListIterator<String> iterator = items.listIterator();

        // 요소 추가 및 삭제 예시
        while (iterator.hasNext()) {
            String item = iterator.next();
            if ("Banana".equals(item)) {
                iterator.add("Blueberry"); // "Banana" 뒤에 "Blueberry" 추가
                iterator.remove(); // "Banana" 삭제
            }
        }
        System.out.println(items); // 출력 결과: [Apple, Blueberry, Cherry]
    }
}

이 코드에서 ListIterator는 "Banana"를 탐색하면서, 해당 위치에 "Blueberry"를 추가하고 "Banana"를 삭제했습니다. 이러한 기능은 요소의 위치를 정확히 제어할 수 있도록 도와주며, ConcurrentModificationException 없이 안전하게 리스트를 수정할 수 있습니다.

 

마무리

  • forEach: 간단하게 요소를 탐색할 때 유용하지만, 리스트 수정은 불가능.
  • Iterator: 단방향 탐색이 가능하며, 탐색 중 안전하게 요소를 삭제할 수 있음.
  • ListIterator: 양방향 탐색과 요소의 추가/삭제 및 수정이 가능하여 유연하게 리스트를 다룰 수 있음.

리스트를 다룰 때 위 탐색 방법들을 상황에 맞게 사용하면 코드의 효율성과 가독성을 모두 높일 수 있습니다. ListIterator는 특히 요소의 추가, 삭제, 수정이 동시에 필요할 때 강력한 도구가 됩니다.

728x90
반응형