티스토리 뷰

Java/Class

7. Collections Framework : Set

알 수 없는 사용자 2018. 10. 25. 21:49


이번 포스팅에서는

Collections Framework 중 하나인

Set 계열의 클래스를 다루어 보겠습니다.

Map을 제외한 Collection들은

각자의 부분적인 특성이 다를 뿐이지

사용하는 큰 틀은 비슷하기 때문에 하나만 이해해도 무방하다고 생각합니다.


==========================================================================


Collections Framework : Set





1. Set : What?


 Set 계열의 Collection 클래스의 공통적인 특징은 중복된 객체를 저장하지 않는다는 것입니다.

배열과 같이 index를 통해 객체를 저장하여 관리하는 List와 달리 Set은 index 매개변수가 존재하지 않습니다.

때문에 저장된 데이터 집합에서 특정한 객체를 다이렉트로 뽑아 사용할 수 없다는 단점이 있습니다.

하지만 중복된 객체를 자동으로 저장하지 않는다는 점과 Collection 간의 집합 / 대규모 연산(bulk operation)이 가능한 장점이 있습니다.







2. Set : HashSet, LinkedHashSet?



 HashSet은 가장 빠른 연산을 처리하지만, 저장하는 데이터의 순서를 보장하지 않습니다.

Set의 중복을 제거한다는 특징과 함께 해시 테이블 구조를 지닙니다. 때문에, hashCode() 메소드에 의해 데이터를 그룹화하고, equals() 메소드를 이용해 중복 객체를 판단합니다. (실제로 객체비교하는 과정은 따로 다루겠습니다.)

 LinkedHashSet은 HashSet을 상속받아 설계된 클래스로 HashSet에서 저장순서를 유지하는 기능만 추가된 클래스입니다.


다음은 HashSet에 포함된 메소드입니다.

[HashSet 클래스에 정의된 메소드]


모든 Collection 클래스들이 복잡하거나 어려운 메소드를 포함하고 있지 않습니다. Collection에서 사용하는 클래스들의 메소드이름은 상당히 비슷하고 유사한 작업을 하므로 하나만 정확하게 익혀두어도 나머지는 이해하기 쉽습니다.


- add() : 새로운 객체를 저장하는 메소드입니다.

- clear() : 저장된 모든 객체를 삭제합니다.

- clone() : HashSet을 복제해서 반환합니다.

- isEmpty() : HashSet이 비어있는지 알려줍니다.

- remove() : 지정된 객체를 HashSet에서 삭제합니다. Set은 index를 가지고 있지 않기 때문에 객체를 인자로 넘겨 같은 객체를 찾아 삭제합니다.

- size() : 저장된 객체의 개수를 반환합니다.

- contains() : 인자로 넘긴 객체가 HashSet 안에 존재하는지 확인합니다.






3. Set : TreeSet?


 LinkedHashSet이 저장순서를 유지하는 Set이라면 TreeSet이진 검색 트리라는 자료구조의 형태로 객체의 크기에 따라 정렬하여 데이터를 관리하는 Collection 클래스입니다.




Tree라는 이름은 각 노드 간의 연결된 모양이 나무와 같다고 해서 붙여진 이름입니다.

각 객체 요소를 노드(node)라 부릅니다. 이러한 노드들이 최대 2개의 노드를 연결할 수 있으며 최상위의 노드를 부르는 루트로부터 계속 확장해 나갈 수 있습니다.


 TreeSet은 크기에 따라 확장한다 하였는데 Integer형 데이터 7, 4, 9, 1, 5의 순서로 값을 TreeSet에 저장한다면 위의 사진과 같이 저장됩니다.

제일 처음 들어오는 7이 루트가 되고 그다음부터 큰 값은 오른쪽 노드로, 작은 값은 왼쪽 노드로 연결 지으면서 저장됩니다.

그 결과 트리에서의 맨 왼쪽 하단 노드는 제일 작은 값이 되고, 맨 오른쪽 하단 노드가 제일 큰 값으로 저장되는 것입니다.


이처럼 TreeSet은 정렬된 상태를 유지하기 때문에 단일 값 검색과 범위 검색에 효율이 좋습니다. 

하지만 데이터를 순차적으로 저장하는 것이 아니기 때문에 데이터를 추가하거나 삭제할 때 트리의 일부를 재구성해야 하므로 데이터의 추가, 삭제의 시간은 오래 걸립니다.


다음은 TreeSet에 설계된 메소드입니다.

[TreeSet의 메소드]


- subset() : 범위 검색을 위한 메소드로 인자로 범위를 전달하여 범위 안의 결과를 반환합니다.

- headSet() : 인자로 전달된 객체보다 작은 값의 객체들을 반환합니다.

- tailSet() : 인자로 전달된 객체보다 큰 값의 객체들을 반환합니다.





4. Set : How?


Set계열의 Collection 클래스들은 구성과 기능은 대부분 비슷하고 데이터 저장관리에서의 특징만 다르기 때문에 LinkedHashSet을 이용해 다루겠습니다.


개인적으로는 Collection의 클래스를 사용할 때 메소드와 기능을 구현하기 위한 과정이 그렇게 어렵게 느껴지진 않았습니다.

하지만 목적에 따른 Set을 사용하면서 어떤 식으로 설계해야 하고 구현될지 머릿속으로 생각하고 상상하면서 공부하면 효과적인 것 같습니다.


public class Source02_Set {
public static void main(String[] args) {
Set set;
set = new LinkedHashSet();
// set = new HashSet();
// set = new TreeSet();

// <> : 어떤 객체값을 저장할것인지 설정하고 설계하는 것을 권장하는데 미 설정시 Object로 설정됨.

        System.out.println("size = " + size); // 0

boolean b = set.isEmpty(); // set에 저장된 객체가 있는지 없는지
        System.out.println("isEmpty = " + b); // true

boolean t = set.add("월요일"); // 객체 저장
        System.out.println(t); // true
boolean t1 = set.add("월요일"); // 중복 객체 저장안함
        System.out.println(t1); // false

int[] ar = new int[3];
boolean t3 = set.add(ar);
System.out.println(t3); // true
System.out.println("size = " + set.size()); // 2 / 월요일 객체와 ar int배열 2

        boolean t4 = set.contains(ar); // set 객체에 ar객체가 존재하는지 검사
System.out.println(t4); // true

System.out.println(set.contains("금요일")); // false

boolean t5 = set.remove(ar); // 해당 객체 삭제
        System.out.println(t5); // true

set.clear(); // 모든 객체 삭제 (void 반환형)
System.out.println(set.size()); // 0

for(int i=0;i<=100000; i++) { // 메모리만 허용한다면 개수 제한은 없다
int[] z = new int[5]; // 자바를 사용하면서 사용할 수 있는 메모리 제한이 있기 때문에 배열 크기를 50000으로 한다면 터짐
set.add(z);
}
System.out.println(set.size());
}
}


Collection의 모든 클래스는 일반 객체를 생성하듯 Collection을 생성하면 됩니다. 

또한 인자로 Collection을 넘겨 생성할 수 있는데 이는 인자로 넘긴 Collection을 포함하는 HashSet 객체를 생성합니다. 





5. Set : Set Operation?


 Collection끼리의 집합 연산이 가능합니다.

여기서 집합 연산이란 합집합, 교지합, 차집합 이런 것을 의미합니다.


public class Source06_Set {
static Set<Integer> makeSample(){
Set<Integer> s = new HashSet<>();
for(int cnt=1;cnt<=5;cnt++) {
int n = 1+(int)(Math.random()*13);
s.add(n);
}
return s;
}

public static void main(String[] args) {
Set<Integer> s1 = makeSample();
Set<Integer> s2 = makeSample();
System.out.println("s1 = " + s1.toString());
System.out.println("s2 = " + s2.toString());

boolean c = s1.containsAll(s2); // s1 s2를 모두 가지고 있나 확인
System.out.println("containsAll = " + c);

boolean b = s1.addAll(s2); // true (합집합)
System.out.println(b + " / s1 = " + s1.toString()); // true
System.out.println(s1.addAll(s2)); // false / 변화가 있어야지만 true

boolean c1 = s1.containsAll(s2);
System.out.println("containsAll = " + c1); // true

boolean c2 = s1.removeAll(s2); // s2값과 같은 것을 s1에서 지움
System.out.println("removeAll = " + c2); // true
boolean c3 = s1.removeAll(s2); // 지울 것이 없기 때문에 false (차집합)
System.out.println("removeAll = " + c3); // false

boolean c4 = s1.retainAll(s2); // removeAll과 반대로 같은 것만 두고 다 삭제(교집합)
System.out.println("retainAll = " + c4); // true
boolean c5 = s1.retainAll(s2); // 삭제된 것이 없어서 false
System.out.println("retainAll = " + c5); // false
}
}


- addAll() : 인자로 전달되는 Collection에 저장된 모든 객체들을 저장합니다. (합집합)

- containsAll() : 인자로 전달되는 Collection에 저장된 모든 객체들을 포함하고 있는지 확인합니다.

- removeAll() : 인자로 전달되는 Collection에 저장된 객체와 동일한 객체를 모두 삭제합니다. (차집힙)

- retainAll() : removeAll()에 반대의 개념으로 인자로 전달되는 Collection에 저장된 객체와 동일한 것만 남기고 삭제합니다. (교집합)


'Java > Class' 카테고리의 다른 글

9. Collections Framework : Queue, Deque  (0) 2018.10.30
8. Collections Framework : List  (0) 2018.10.29
6. Collections Framework  (0) 2018.10.23
5. Wrapper Class  (0) 2018.10.22
4. 정규표현식(Regular Expression) : java.util.regex 패키지  (0) 2018.10.19
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
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
글 보관함