2018-6-5 Collection Framework (2) - Set

Set Interface

Set<E>를 구현하는 클래스의 특성과 HashSet<E>

Set<E> 인터페이스의 특징

  1. 저장 순서가 유지되지 않는다.
  2. 데이터의 중복을 허락하지 않는다.

set은 수학에서 말하는 집합의 특성이다.

package yoon;

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

public class SetCollectionFeature {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("Toy");
        set.add("Box");
        set.add("Robot");
        set.add("Box");
        System.out.println("인스턴스의 수 : " + set.size());

        for(Iterator<String> itr = set.iterator(); itr.hasNext(); )
            System.out.print(itr.next() + "\t");
        System.out.println();

        for (String s: set)
            System.out.print(s + "\t");
        System.out.println();
    }
}
//result
인스턴스의 수 : 3
Box	Robot	Toy
Box	Robot	Toy
  • Set에서 동일한 인스턴스로 판단하는 기준은 무엇일까?
package yoon;

import java.util.HashMap;
import java.util.HashSet;

class Num {
    private int num;
    public Num(int n) { num = n; }

    @Override
    public String toString() {
        return String.valueOf(num);
    }
}

public class HashSetEqualityOne {
    public static void main(String[] args) {
        HashSet<Num> set = new HashSet<>();
        set.add(new Num(7799));
        set.add(new Num(9955));
        set.add(new Num(7799));
        System.out.println("인스턴스의 수 : " + set.size());

        for(Num n : set)
            System.out.print(n.toString() + "\t");
        System.out.println();
    }
}
//result
인스턴스의 수 : 3
7799	7799	9955
  • 위의 7799는 서로 같은 값을 가지고 있지만, 다른 인스턴스로 바라보기 때문에 출력이 된다.
  • Hash<E>이 판단하는 동일 인스턴스의 기준은 Object 클래스에 정의되어있는 두 가지 메소드 호출 근거를 바탕으로 한다.
  1. public boolean equals(Object obj)
  2. public int hashCode()

Hash Algorithm & HashMethod

  • 다음의 수들을 num % 3연산을 통해 결과를 분류해보자
  • 3, 5, 7, 12, 25, 31

  • 위의 결과에서 정수5의 존재 여부를 확인하는 방법
  • 5 % 3 = 2이므로 연산결과가 0,1은 제외를 시킨다.
  • 탐색 1 단계 : 정수5의 해쉬 값을 계산하여 부류결정
  • 탐색 2 단계 : 선택된 부류 내에 정수 5가 존재하는지 확인
  • 그리고 HashSet을 이용해서 인스턴스의 존재여부 확인
public class HashSetEqualityOne {
    public static void main(String[] args) {
        HashSet<Num> set = new HashSet<>();
        set.add(new Num(7799));
        set.add(new Num(9955));
        set.add(new Num(7799));

    }
}
  • hashCode메소드는 인스턴스가 저장된 주솟값을 기반으로 반환값이 만들어진다.
  • 인스턴스가 다르면 Object클래스의 hashCode메소드는 다른 값을 반환한다.
  • 인스턴스가 다르면 Object클래스의 equals메소드는 false를 반환한다.
  • 그러므로 7799를 동일하게 바라보려면 위의 두 메소드를 오버라이딩을 해야한다.
package yoon;

import java.util.HashSet;

class Num {
    private int num;
    public Num(int n) { num = n; }

    @Override
    public String toString() {
        return String.valueOf(num);
    }

    @Override
    public int hashCode() {
        return num % 3; // num의 값이 같으면 부류도 같다.
    }

    @Override
    public boolean equals(Object obj) {
        if(num == ((Num)obj).num)
            return true;
        else
            return false;
    }
}

public class HashSetEqualityTwo {
    public static void main(String[] args) {
        HashSet<Num> set = new HashSet<>();
        set.add(new Num(7799));
        set.add(new Num(9955));
        set.add(new Num(7799));
        System.out.println("인스턴스 수 : " + set.size());

        for(Num n : set)
            System.out.print(n + "\t");
        System.out.println();
    }
}
//result
인스턴스 수 : 2
9955	7799
Written on June 5, 2018