본문 바로가기
자바/자바 자료구조

자바 - Set 이야기

by 신재은👩🏼‍💻 2024. 4. 28.

Set이 뭐 별 거 있나.

중복 안 돼야 되면 셋 쓰는 거지...

 

Java에서 Set은 컬렉션 프레임워크의 인터페이스 중 하나로, 중복을 허용하지 않는 데이터의 집합을 관리하는 데 사용됩니다. Set 인터페이스는 Collection 인터페이스를 확장하며, 요소의 순서를 보장하지 않는 특성이 있습니다. Set은 값의 존재 유무를 체크하거나, 중복을 제거하는 등의 작업에서 유용하게 사용됩니다.

Java에서 사용할 수 있는 주요 Set 구현체

  1. HashSet
    1. 가장 많이 사용되는 Set 구현체입니다.
    2. 내부적으로 HashMap을 사용하여 요소를 저장합니다.
    3. 요소의 추가, 삭제, 조회 작업의 시간 복잡도는 평균적으로 O(1)입니다.
    4. 요소의 순서를 유지하지 않으며, null 값도 저장할 수 있습니다.
  2. LinkedHashSet
    1. HashSet의 확장으로, 요소가 추가된 순서대로 순회할 수 있습니다.
    2. 내부적으로 LinkedHashMap을 사용하여 요소를 저장합니다.
    3. HashSet의 모든 특성을 가지고 있으면서 추가적으로 요소의 삽입 순서를 유지합니다.
  3. TreeSet
    1. 레드-블랙 트리 기반의 NavigableSet 구현체입니다.
    2. 요소가 자동으로 정렬되며, 기본적으로 자연 순서대로 정렬되거나 생성자에서 제공된 Comparator에 따라 정렬됩니다.
    3. 요소의 추가, 삭제, 조회 작업의 시간 복잡도는 O(log n)입니다.
    4. null 값은 허용하지 않으며 (단, Comparator를 사용하여 null을 허용하도록 설정할 수 있습니다), 중복된 값을 저장하지 않습니다.

진짜 쉽지 않나?

보통은 HashSet, 요소가 추가된 순서가 중요하면 LinkedHastSet, 정렬해야 되면 TreeSet!

Set 인터페이스의 주요 메서드

  • add(E e): 요소 e를 집합에 추가합니다. 요소가 성공적으로 추가되면 true를 반환하고, 이미 존재하는 요소라면 false를 반환합니다.
  • remove(Object o): 주어진 객체 o를 집합에서 제거합니다. 성공적으로 제거되면 true를 반환합니다.
  • contains(Object o): 집합에 특정 객체 o가 포함되어 있는지 확인합니다. 포함되어 있으면 true를 반환합니다.
  • size(): 집합의 요소 수를 반환합니다.
  • isEmpty(): 집합이 비어 있는지 확인합니다. 비어 있으면 true를 반환합니다.
  • clear(): 집합의 모든 요소를 제거합니다.
  • iterator(): 집합의 요소를 순회할 수 있는 Iterator를 반환합니다.

코딩 테스트에서 Set 사용 예

import java.util.HashSet;
import java.util.Set;

public class Example {
    public static void main(String[] args) {
        Set<Integer> numbers = new HashSet<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(2); // 이 요소는 추가되지 않음

        System.out.println(numbers.contains(1)); // 출력: true
        System.out.println(numbers.size()); // 출력: 2
    }
}

사용 시나리오

  • 중복 제거: 데이터에서 중복을 제거해야 할 때 Set을 사용할 수 있습니다.
  • 데이터 멤버십 테스트: 데이터 집합에서 특정 요소의 존재 여부를 빠르게 테스트해야 할 때 사용합니다.
  • 데이터 집합 연산: 두 집합 간의 교집합, 합집합, 차집합 등을 구할 때 유용합니다.

Set은 매우 다양한 상황에서 중요한 역할을 할 수 있는 자료구조로, 코딩 테스트에서도 매우 유용하게 사용됩니다. 각 구현체의 특성을 잘 이해하고 필요에 따라 적절히 선택하여 사용하면, 많은 문제를 효과적으로 해결할 수 있습니다.

https://www.geeksforgeeks.org/set-in-java/

 

자바에서 Iterable과 Collection 인터페이스는 자료구조의 기본적인 구현을 위한 프레임워크를 제공합니다. Iterable 인터페이스는 클래스가 "for-each loop"를 통해 반복될 수 있도록 합니다. 즉, 클래스가 Iterable을 구현하면 그 인스턴스들은 반복 가능하며, iterator() 메소드를 통해 Iterator 객체를 제공해야 합니다.

 

Collection 인터페이스는 Iterable을 확장하며, 데이터 그룹을 관리하는 데 필요한 메소드들(추가, 삭제, 크기 조회 등)을 정의합니다. Collection 인터페이스는 List, Set, Queue 등과 같은 더 구체적인 데이터 구조 인터페이스들의 상위 인터페이스입니다.

 

그러나 자바는 Iterable과 Collection 인터페이스에 속하지 않는 자료구조도 제공합니다. 몇 가지 예를 들어보면:

  1. 배열(Array): 기본 데이터 타입이나 객체 참조들의 연속된 컬렉션을 저장합니다. 배열은 Iterable을 구현하지 않으며, 크기가 고정됩니다.

그런데 배열이 이터러블을 구현하지 않는다는 말에 좀 걸리는 사람 없으려나?

어레이리스트 같은 것도 이터러블 구현하지만 for문 쓰고

어레이도 for문 돌려서 순회하잖아...

더보기

배열이 Iterable 인터페이스를 직접 구현하지 않는다는 말은, 배열 자체에 iterator() 메서드가 없다는 것을 의미합니다. Java에서 Iterable 인터페이스는 객체가 "foreach" 루프(즉, 향상된 for 루프)를 통해 순회될 수 있게 하는 데 필요한 메서드인 iterator()를 제공해야 합니다.

배열과 Iterable

Java에서 배열은 본질적으로 원시 데이터 구조로, 배열의 각 요소에 접근하기 위해서는 인덱스를 사용합니다. 배열에는 iterator() 메서드가 포함되어 있지 않기 때문에, Iterable 인터페이스를 직접 구현하지 않습니다. 그러나 Java의 향상된 for 루프는 배열을 자동으로 처리할 수 있는 내부 메커니즘이 있어, 별도의 이터레이터 없이도 배열의 각 요소를 순차적으로 접근할 수 있습니다.

int[] numbers = {1, 2, 3, 4, 5};
for (int number : numbers) {
    System.out.println(number);
}

 

 

위 코드에서 배열 numbers는 향상된 for 루프를 사용하여 각 요소를 출력할 수 있지만, 이는 Iterable 인터페이스 덕분이 아니라 Java 언어가 배열을 자동으로 처리하기 때문입니다. <- 와우네...

ArrayList와 Iterable

반면에 ArrayList와 같은 컬렉션 클래스들은 Collection 인터페이스를 확장하며, Collection은 Iterable 인터페이스를 구현하므로 ArrayList는 Iterable 인터페이스를 구현합니다. 이는 ArrayList가 iterator() 메서드를 제공하며, 이 메서드는 ArrayList의 각 요소를 순회할 수 있는 Iterator 객체를 반환합니다.

import java.util.ArrayList;

ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
for (Integer item : list) {
    System.out.println(item);
}

 

 

이 코드에서 list는 ArrayList 인스턴스이며, 향상된 for 루프를 사용할 때 내부적으로 list.iterator()를 호출하여 Iterator 객체를 얻고, 이 객체를 통해 리스트의 요소를 하나씩 순회합니다. <- 와우다, 진짜!!! 너무 신기해!!!

결론

즉, 배열이 Iterable을 구현하지 않는다는 말은 배열이 iterator() 메서드를 갖고 있지 않으며, Iterable 인터페이스의 일부가 아니라는 뜻입니다. 그러나 Java 언어는 배열을 향상된 for 루프에서 사용할 수 있도록 특별히 지원합니다. 반면, ArrayList와 같은 컬렉션은 Iterable 인터페이스를 통해 향상된 for 루프와 호환됩니다.

 

난... 정말 GPT가 좋다...

  1. 맵(Map): 키-값 쌍을 저장하는 자료구조로, Collection 인터페이스를 구현하지 않습니다. 대표적인 예로는 HashMap, TreeMap, LinkedHashMap 등이 있습니다. 맵은 직접적으로 Iterable을 구현하지는 않지만, 맵의 키 셋, 값 콜렉션, 또는 키-값 쌍 엔트리 셋은 Iterable을 구현합니다.
  2. 스택(Stack): Stack 클래스는 레거시 클래스이며 Vector를 확장합니다. Deque 인터페이스와 ArrayDeque 구현을 사용하여 현대적인 스택 기능을 사용하는 것이 권장됩니다.
  3. 프라이어리티 큐(PriorityQueue): 이는 Collection 인터페이스를 구현하지만, 일반적인 큐의 FIFO(First-In-First-Out) 특성 대신 요소의 우선순위에 따라 요소를 정렬합니다.

이러한 예외들은 자바가 Iterable과 Collection 프레임워크 외에도 다양한 유형의 자료구조를 지원함을 보여줍니다. 자바의 자료구조는 매우 다양하며, 각각의 구체적인 요구 사항과 사용 사례에 맞춰 선택할 수 있습니다.


나 그럼 진짜 다 한 거 같은데???

그럼 이제 Set 관련 문풀 3개만 하면 진짜 끝입니다!