본문 바로가기

BackEnd/구 생활코딩 자바

Set<E> 인터페이스를 구현하는 컬렉션 클래스들

반응형


1. Set<E> 인터페이스를 구현하는 제네릭 클래스들의 공통점

1) 동일한 인스턴스의 중복 저장을 허용하지 않는다.

2) 인스턴스의 저장 순서를 유지하지 않는다.

3) 즉,  집합의 성격을 지닌다.


2.  Set<E> 인터페이스를 구현하는 제네릭 클래스들

1) HashSet<E>

- HashSet<E>은 중복저장을 판담함에 있어서 기본적으로 인스턴스의 참조값을 기준으로 중복을 판단한다.

 그러므로 프로그래머가 equals메소드를 오버라이딩 함으로써 중복저장에 대한 기준을 세워줘야 한다.

- HashSet<E>은 해시 알고리즘을 적용하여 hashCode 메소드를 오버라이딩 함으로써 성능을 개선 할 수 있다.


아래는 HashSet이 중복을 허용하지 않고 순서를 유지하지 않음을 보여준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.Iterator;
import java.util.HashSet;
 
class a07_SetInterfaceFeature
{
    public static void main(String[] args)
    {
        HashSet<String> hSet=new HashSet<String>();
 
        hSet.add("First");
        hSet.add("Second");
        hSet.add("Third");
        hSet.add("First");
        
        System.out.println("저장된 데이터 수: "+hSet.size());
        
        Iterator<String> itr=hSet.iterator();
        while(itr.hasNext())
            System.out.println(itr.next());
    }
}
cs


출력

1
2
3
4
저장된 데이터 수: 3
Second
Third
First
cs


아래는 HashSet은 중복의 판단여부를 equals메소드로 판단함을 보여준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.util.Iterator;
import java.util.HashSet;
 
class SimpleNumber
{
    int num;
    public SimpleNumber(int n)
    {
        num=n;
    }
    public String toString()
    {
        return String.valueOf(num);//int를 스트링으로
        //String 클래스의 static 메소드인 valueOf 는 기본 자료형 데이터를 String 인스턴스로 변환해 준다.
    }
}
 
class a08_HashSetEqualityOne
{
    public static void main(String[] args)
    {
        HashSet<SimpleNumber> hSet=new HashSet<SimpleNumber>();
        hSet.add(new SimpleNumber(10));
        hSet.add(new SimpleNumber(20));
        hSet.add(new SimpleNumber(20));//인스터스마다 다른주소값이니까 다른 걸로 인식해서 중복값이 출력
        //HashSet은 equals메소드로 동등비교를 한다 equals메소드는 주소값을 비교한다.
        //같은값으로 인식하길 원한다면 내가 equals메소드를 오버라이딩해야한다
        
        System.out.println("저장된 데이터 수: "+hSet.size());
        
        Iterator<SimpleNumber> itr=hSet.iterator();
        
        while(itr.hasNext())
            System.out.println(itr.next());
    }
}
cs


출력

1
2
3
4
5
저장된 데이터 수: 3
10
20
20
 
cs


아래는 hashCode 메소드와 equals메소드를 오버라이딩해서 중복값을 제거해줬다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import java.util.Iterator;
import java.util.HashSet;
 
class SimpleNumber2
{
    int num;
    public SimpleNumber2(int n)
    {
        num=n;
    }
    public String toString()
    {
        return String.valueOf(num);
    }
    public int hashCode()//해시코드는 성능을 개선해주는것이다 num 값을 3으로 나눠서 분류해둔다
    {
        return num%3;
    }
    public boolean equals(Object obj) // 이 메소드의 리턴값으로 해시셋의 중복여부를 결정한다
    {
        SimpleNumber2 comp=(SimpleNumber2)obj;
        if(comp.num==num)
            return true;
        else
            return false;        
    }
}
 
class a09_HashSetEqualityTwo
{
    public static void main(String[] args)
    {
        HashSet<SimpleNumber2> hSet=new HashSet<SimpleNumber2>();
        hSet.add(new SimpleNumber2(10));
        hSet.add(new SimpleNumber2(20));
        hSet.add(new SimpleNumber2(20));
        
        System.out.println("저장된 데이터 수: "+hSet.size());
        
        Iterator<SimpleNumber2> itr=hSet.iterator();
        while(itr.hasNext())
            System.out.println(itr.next());
    }
}

cs


출력

1
2
3
4
저장된 데이터 수: 2
10
20
 
cs


2) TreeSet<E>

 - TreeSet<E>은 ‘트리(Tree)’라는 자료구조를 기반으로 구현되어 있는데 데이터를 정렬된 상태로 저장하는 

   자료구조이다. 이는 저장순서(오름차순,내림차순)를 유지하는 것과 의미가 완전히 다르다.

   인스턴스의 정렬의 기준(인스턴스의 대소 비교)은 프로그래머가 정의해야한다.

 - 데이터의 중복을 허용하지 않는다.


아래에서는 나이와 이름이라는 2가지 정보가 존재하기 때믄에 정렬의 기준을 정해줘야한다.

아래는 인스턴스 변수 age의 값의 크고 작음을 기준으로 정렬하였다.

정렬을 위해서는 Comparable 을 구현하고 comparaTo 메소드를 오버라이딩 해줘야한다.

왜냐하면 TreeSet은 comparaTo 메소드의 호출결과를 참조하여 정렬을 하기때문이다.

이렇게 구현해줘야 TreeSet은 인스턴스를 저장할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import java.util.Iterator;
import java.util.TreeSet;
 
class Person implements Comparable<Person>//Comparable을 구현해야함
{
    String name;
    int age;
 
    public Person(String name, int age)
    {
        this.name=name;
        this.age=age;
    }
    public void showData()
    {
        System.out.printf("%s %d \n", name, age);
    }
    //Comparable 클래스의 compareTo메소드를 오버라이딩해서 정렬의 기준을 정하자
    public int compareTo(Person p) //정렬의 기준을 나이가 많고 적음으로 표현한거지 오름차순인지 내림차순인지는 정하지않음
    {
        if(age>p.age) //인자로 전달된 p의  키가 더 작다면 1반환
            return 1;
        else if(age<p.age)//크다면 -1
            return -1;
        else    
            return 0;//같다면 0
    }
}
class a11_ComparablePerson 
{
    public static void main(String[] args)
    {
        TreeSet<Person> sTree=new TreeSet<Person>();
        sTree.add(new Person("Lee"24));
        sTree.add(new Person("Hong"29));
        sTree.add(new Person("Choi"21));
        
        Iterator<Person> itr=sTree.iterator();//이터레이터가 오름차순으로 참조한다
        
        while(itr.hasNext())
            itr.next().showData();
    }
}
cs


출력

1
2
3
Choi 21 
Lee 24 
Hong 29 
cs


아래에서도 마찬가지로 

Integer 클래스는 Comparable을 구현하고 comparaTo 메소드를 오버라이딩 하여 정렬의 기준이 세워져 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.Iterator;
import java.util.TreeSet;
 
class a10_SortTreeSet
{
    public static void main(String[] args)
    {
        TreeSet<Integer> sTree = new TreeSet<Integer>();
        sTree.add(1);
        sTree.add(2);
        sTree.add(4);
        sTree.add(3);
        sTree.add(2);//중복 허용안함    
        
        System.out.println("저장된 데이터 수: "+sTree.size());
        
        Iterator<Integer> itr=sTree.iterator();//이터레이터는 정렬된 데이터를 항상 오름차순으로 참조
        while(itr.hasNext())
            System.out.println(itr.next());
    }
}
cs


출력

1
2
3
4
5
저장된 데이터 수: 4
1
2
3
4
cs


아래에서는 String 클래스는 사전편찬 순으로 정렬이 되도록 comparaTo 메소드가 오버라이딩 되어 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.TreeSet;
import java.util.Iterator;
 
class a12_ComparableString
{
    public static void main(String[] args)
    {
        TreeSet<String> tSet=new TreeSet<String>();        
        tSet.add("Orange");
        tSet.add("Apple");
        tSet.add("Dog");
        tSet.add("Individual");
        
        Iterator<String> itr=tSet.iterator();
        while(itr.hasNext())
            System.out.println(itr.next());
    }
}
cs


출력

1
2
3
4
5
Apple
Dog
Individual
Orange
 
cs



아래는 문자열의 길이를 기준으로 정렬하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import java.util.TreeSet;
import java.util.Iterator;
 
class MyString implements Comparable<MyString>
{
    String str;
    
    public MyString(String str)
    {
        this.str=str;
    }
    
    public int getLength()
    {
        return str.length();
    }
    
    public int compareTo(MyString mStr)
    {
        if(getLength()>mStr.getLength())//인자로 전달된 문자열의 길이가 더작다면 1반환
            return 1;
        else if(getLength()<mStr.getLength())
            return -1;
        else
            return 0;
 
        //return getLength()-mStr.getLength();//위를 요렇게 표현해도됨
         
    }
    
    public String toString()
    {
        return str;
    }
}
 
class a13_ComparableMyString
{
    public static void main(String[] args)
    {
        TreeSet<MyString> tSet=new TreeSet<MyString>();        
        tSet.add(new MyString("Orange"));
        tSet.add(new MyString("Apple"));
        tSet.add(new MyString("Dog"));
        tSet.add(new MyString("Individual"));
        
        Iterator<MyString> itr=tSet.iterator();//오름차순정렬 길이가짧은것부터
        while(itr.hasNext())
            System.out.println(itr.next());
    }
}
cs


출력

1
2
3
4
5
Dog
Apple
Orange
Individual
 
cs


아래는 별도의 클래스 정의없이 기존의 String클래스를 활용해 길이순으로 문자열을 정렬한것이다.

Comparator 인터페이스를 구현하고 compare 메소드를 오버라이딩하였다.

그리고 TreeSet은 생성과정에서 Comparator 인터페이스를 구현하는 인스턴스의 참조값이 전달되었다.

이렇게 되면 TreeSet은 compare 메소드를 호출하여 정렬을 진행한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.util.TreeSet;
import java.util.Iterator;
import java.util.Comparator;
 
class StrLenComparator implements Comparator<String>
{
    public int compare(String str1, String str2)
    {
        if(str1.length()> str2.length())
            return 1;
        else if(str1.length()< str2.length())
            return -1;
        else
            return 0;
        
        /*
         * return str1.length()-str2.length();
         */
    }
}
 
class a14_IntroComparator
{
    public static void main(String[] args)
    {
        TreeSet<String> tSet=new TreeSet<String>(new StrLenComparator());        
        tSet.add("Orange");
        tSet.add("Apple");
        tSet.add("Dog");
        tSet.add("Individual");
        
        Iterator<String> itr=tSet.iterator();
        while(itr.hasNext())
            System.out.println(itr.next());
    }
}
cs

출력

1
2
3
4
5
Dog
Apple
Orange
Individual
 
cs


반응형