728x90

1. Set<E>



자바 컬렉션 프레임워크(Collection Framework)에서 제공하는 인터페이스로, 중복되지 않는 요소들을 유일하게 저장하는 컬렉션입니다. 집합의 개념으로 인덱스 정보를 포함하고 있지 않고, 중복된 요소를 허용하지 않는 순서가 없는 데이터 그룹을 저장하는 인터페이스입니다. 인덱스 정보가 없기때문에 중복된 원소 중 특정 위치 값을 꺼낼 방법이 없습니다.

생성된 객체에서 데이터를 추가하고 출력할 때는 index 정보가 없기때문에 정렬 되어있는 상태가 아닌 주머니에 무작위하게 들어있기 때문에 순서가 보장되지 않습니다.(null 값 조차 한 개만 포함이 가능) 대표적인 클래스로는 HashSet, LinkedHashSet. TreeSet 등이 있습니다.

 

  • set<E> 컬렉션의 특징 : index 정보가 없기 때문에 중복저장이 불가능하기 때문에 중복저장이 가능한지 불가능한지를 판단하는 기준이 될 수 있습니다.

✅ 대표적인 Set<E> 컬렉션의 클래스


1. HashSet<E> : Set<E> 인터페이스를 구현한 클래스 중 하나로, 해시 테이블을 사용하여 요소들을 저장하는 자료구조입니다. 수집(collect)한 원소(Element)를 집합의 형태로 관리하며 저장용량( capacity - 16)을 동적 관리합니다. 입력의 순서와 출력의 순서는 동일하지 않을 수 있으며, HashSet<E>은 일반적으로 요소들의 집합을 관리하고 중복을 제거하는 데에 사용됩니다. 예를 들어, 어떤 항목들의 목록에서 중복된 항목을 제거하고 유일한 항목들을 가져와야 할 때 HashSet<E>을 사용할 수 있습니다. 또한 해시 테이블의 특성상 빠른 검색이 필요한 경우에도 유용하게 사용됩니다. ** Hash - 중복된 데이터들의 저장이 안되려면 다름과 같음을 비교해주기 때문에 중복의 확인이 필요합니다.

  • Iterator<E> (for-each로 대체 가능) : Set<E>은 index정보가 없기때문에 순서대로 요소출력이 어려운데 interator 메서드를 사용하면 set에서 컬렉션 내의 요소를 순차적으로 접근하고 삭제할 수 있는 방법을 제공합니다.
  • Set은 순서자체를 가지고 있지 않기 때문에 순서라는 것은 의미가 없지만 Iterator메서드는 모든 데이터요소에 한번씩 접근해 출력이 가능합니다. 컬렉션의 내부 구조에 상관없이 일관된 방식으로 요소에 접근할 수 있도록 합니다.
      1. hasNext() : Iterator가 다음 요소를 가지고 있는지 확인합니다. 다음 요소가 있을 경우 true를 반환하고, 없을 경우 false를 반환합니다.
      2. next() : Iterator의 현재 위치에서 다음 요소를 반환합니다. 반환된 요소는 컬렉션 내의 다음 요소로 이동합니다.
        • HashSet에서 요소의 중복 여부를 판단하기 위해 hashCode()와 equals() 메서드를 사용합니다.
          • hashCode() 메서드는 객체의 해시 코드를 반환하는 메서드입니다. HashSet은 요소를 저장할 때 요소의 hashCode() 값을 사용하여 해시 테이블에 저장하고 관리합니다.
            저장된 코드 값은 패키지명.클래스명@hashCode가 출력됩니다. 1단계로 동일한 hashCode() 값을 갖는 다른 요소들이 있다면 2단계로 equals() 메서드로 비교하여 중복 여부를 확인합니다.
            hashCode() 메서드는 객체의 내부 상태에 기반하여 정수 값을 반환하는데, 동일한 객체라면 항상 같은 hashCode() 값을 반환해야 합니다.
            HashSet에서 요소의 중복 여부를 판단하기 위해 hashCode() 값을 사용하는 이유는 해시 테이블의 성능을 향상시키기 위해서입니다. 따라서, HashSet을 사용하는 클래스에서는 hashCode() 메서드를 적절히 오버라이딩하여 동일한 객체에 대해 동일한 hashCode() 값을 반환하도록 구현해야 합니다.

          • equals() 메서드는 두 객체가 동등한지 비교하는 메서드입니다. HashSet은 요소의 중복 여부를 판단할 때 equals() 메서드를 사용합니다. HashSet에 이미 저장된 요소와 새로 추가하려는 요소를 equals() 메서드로 비교하여 중복 여부를 확인합니다. equals() 메서드가 true를 반환하는 경우 HashSet은 해당 요소를 중복된 요소로 간주하고 추가하지 않습니다.

          • Iterator<E> (for-each로 대체 가능) : Set<E>은 index정보가 없기때문에 순서대로 요소출력이 어려운데 interator 메서드를 사용하면 set에서 컬렉션 내의 요소를 순차적으로 접근하고 삭제할 수 있는 방법을 제공합니다.
             
            • Set은 순서자체를 가지고 있지 않기 때문에 순서라는 것은 의미가 없지만 Iterator메서드는 모든 데이터요소에 한번씩 접근해 출력이 가능합니다. 컬렉션의 내부 구조에 상관없이 일관된 방식으로 요소에 접근할 수 있도록 합니다.
              1. hasNext() : Iterator가 다음 요소를 가지고 있는지 확인합니다. 다음 요소가 있을 경우 true를 반환하고, 없을 경우 false를 반환합니다.
              2. next() : Iterator의 현재 위치에서 다음 요소를 반환합니다. 반환된 요소는 컬렉션 내의 다음 요소로 이동합니다.


2. TreeSet<E> : TreeSet<E>은 이진 검색 트리의 형태로 요소를 저장하며, 요소들은 정렬된 순서로 저장됩니다. 중복 요소를 허용하지 않으며, 요소들은 자동으로 정렬된 순서로 저장됩니다.
요소들은 기본적으로 오름차순으로 정렬되지만, 요소를 정렬하는 기준을 커스터마이즈할 수도 있습니다. 이진 검색 트리의 성질을 활용하여 요소의 삽입, 삭제, 검색 등의 작업을 빠르게 수행할 수 있습니다.
TreeSet은 Comparable 인터페이스를 구현하는 요소 클래스를 사용하거나, 생성자에 Comparator를 지정하여 요소들의 정렬 기준을 설정할 수 있습니다.
요소 클래스가 Comparable을 구현하지 않고, 별도의 정렬 기준을 지정하지 않으면 요소의 클래스는 **ClassCastException**을 발생시킬 수 있습니다.

  • TreeSet<E> = Set<E>의 기본기능 + 정렬/검색 기능 추가

         public class Ex1_TreeSetBasic {

                public static void main(String[] args) {

                    TreeSet<Integer> treeSet = new TreeSet<>();

                    for (int i = 50; i >0; i-=2) {  treeSet.add(i);      }
                    System.out.println(treeSet.toString());
                    //출력 : [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50]


                    //#1.first() : 정렬된 순서에서 가장 작은 객체를 반환
                    System.out.println(treeSet.first()); //출력 : 2


                    //#2.last() : 정렬된 순서에사 가장 큰 (마지막 순서) 객체를 반환
                    System.out.println(treeSet.last()); //출력 : 50 


                    //#3.lower(E element) : 매개변수로 입력된 원소보다 작은 수들 중 가장 큰 수를 리턴
                    System.out.println(treeSet.lower(26)); //출력 : 24


                    //#4.higher() : 매개변수로 입력된 원소보다 큰 수들 중 가자 작은 수를 리턴
                    System.out.println(treeSet.higher(26)); //출력 : 28


                    //#5.floor(E element) : 입력된 매개변수의 원소와 비교하여 같거나 작은 수들 중 가장 큰 수를 리턴
                    System.out.println(treeSet.floor(25)); //출력 : 24
                    System.out.println(treeSet.floor(26)); //출력 : 26


                    //#6.ceiling(E element) : 입격된 매개변수의 원소와 비교하여 같거나 큰 수들 중 가장 작은 수를 리턴
                    System.out.println(treeSet.ceiling(25)); //출력 : 26
                    System.out.println(treeSet.ceiling(26)); //출력 : 26

 

TreeSet에서 요소들의 크기 비교는 Comparable 인터페이스 또는 Comparator를 통해 이루어집니다.

  1. Comparable 인터페이스를 구현한 요소 클래스를 사용하는 경우 - java.lang.Comparable<T> interface 구현 Comparable 인터페이스를 구현한 클래스의 객체는 compareTo() 메서드를 오버라이드하여 구현해야 합니다. 이 메서드는 두 개의 객체를 비교하여 순서를 결정합니다. TreeSet은 이 메서드를 사용하여 요소들을 정렬하고 크기를 비교합니다. 예를 들어, **treeSet.add(obj)**로 TreeSet에 객체를 추가하면 TreeSet은 **obj.compareTo()**를 호출하여 요소의 크기를 비교하고 적절한 위치에 삽입합니다.

  2. Comparator를 사용하는 경우- java.util.Comparator<T> interface 객체 제공 Comparator는 Comparable을 구현하지 않은 클래스의 요소들을 정렬하기 위해 사용됩니다. Comparator는 compare() 메서드를 구현해야 합니다. TreeSet의 생성자나 **treeSet.add(obj)**와 같은 메서드에 Comparator를 전달하여 TreeSet의 정렬 기준을 지정할 수 있습니다. Comparator를 사용하면 Comparable을 구현하지 않은 클래스의 요소들도 TreeSet에 저장할 수 있습니다.

크기 비교의 결과는 다음과 같습니다:

  • compareTo() 또는 compare() 메서드가 0보다 작은 값 (-1) 을 반환하면, 첫 번째 객체는 두 번째 객체보다 작은 것으로 간주됩니다.
  • compareTo() 또는 compare() 메서드가 0을 반환하면, 두 객체는 동일한 크기로 간주됩니다.
  • compareTo() 또는 compare() 메서드가 0보다 큰 값(1)을 반환하면, 첫 번째 객체는 두 번째 객체보다 큰 것으로 간주됩니다.
           
           class MyClass {
                int data1;
                int data2;

                public MyClass(int data1 ,  int data2) {
                    this.data1 = data1;
                    this.data2 = data2;
                }
            }
            
            //상속과 다형성에 의해서 부모:Comparable 자식 : MyComparableClass 
            class MyComparableClass implements Comparable<MyComparableClass> {
                //MyComparableClass라는 타입을 <>에 작성해 주었고, 이 클래스는 비교에 관련된 내용을 포함시키는데,
                //Comparable이라는 인터페이스를 implements로 구현해주어야 합니다. 
                int data1;
                int data2;

                public MyComparableClass  (int data1 ,  int data2) {
                    this.data1 = data1;
                    this.data2 = data2;
                }
                
                
                //Comparable 인터페이스 안에는 미완성 메서드가 있는데 이 메서드는 compareTo이며, 
                //이 메서드 안에서 대소 크기비교의 기준을 설정 할 수 있습니다. (음수, 0, 양수)
                @Override
                public int compareTo(MyComparableClass o) {
                    if (this.data1 < o.data1) return -1;
                    else if (this.data1 == data2) return 0;
                    else return 1;
                }
            }
728x90
반응형

+ Recent posts