프로그래밍 언어/Java

Java Collections Framework(JCF)란? - Set (JAVA)

제이온 (Jayon) 2021. 2. 13.

안녕하세요? 제이온입니다.

 

오늘은 Set 인터페이스에 대해 알아보겠습니다.

 

 

Set Interface

Set 자료구조는 중복된 요소를 저장하지 않고, 요소의 저장 순서를 유지하지 않는 특징이 있습니다. 주로 HashSet, LinkedHashSet, TreeSet 클래스를 통해 구현합니다.

 

그렇다면, 중복된 요소를 어떻게 걸러낼까요? 바로, Set 인터페이스 내의 정의된 equals()와 hashCode()를 사용하는 것입니다.

 

먼저, 객체를 저장하기 전에 객체의 hashCode()를 호출해서 해시 코드를 얻어냅니다. 저장되어 있는 객체들의 해시 코드와 비교한 뒤 같은 해시 코드가 있다면 다시 equals() 메소드로 두 객체를 비교합니다. 이때, true가 나오면 동일한 객체로 판단하고 중복 저장을 하지 않습니다

 

아래는 equals()와 hashCode() 외의 다른 Set 내장 메소드입니다.

 

 

 

 

이 외에 컬렉션 인터페이스에도 상속을 받으므로 컬렉션 인터페이스의 메소드도 이용이 가능합니다.

 

 

HashSet Class

Set을 이용하기 위해 가장 많이 사용하는 구현 클래스입니다. HashSet은 해시 알고리즘을 사용하여 검색 속도가 빠르다는 장점이 있습니다. 그리고 HashSet은 중복된 요소를 저장하지 않고, 요소의 순서도 저장하지 않습니다.

 

 

 

 

위 사진은 HashSet의 생성자입니다. 설명을 잘 읽어보면, 내부적으로 해시맵 인스턴스를 이용하여 요소를 저장한다고 합니다. 그리고 초기 용량은 16이고, load factor는 0.75라고 되어있습니다. 물론, 이 용량과 load factor는 개발자가 자유롭게 설정이 가능합니다.

 

용량과 load factor에 대한 이야기는 HashTable에서 자세히 다룰 것이므로 간단하게 짚고 넘어가겠습니다. 용량과 load factor의 관계는 '저장된 요소의 수 = 용량 * load factor'라고 이해하셔도 좋습니다. 용량이 고정되어있을 때, 요소를 늘린다면 load factor도 커지게 되는데, 어느 순간 load factor가 0.75에 도달하게 되면 용량을 약 두 배로 늘립니다.

 

또한, HashSet이 해시 알고리즘을 사용한다고 하였는데, 이부분도 HashTable을 설명할 때 같이 다룰 것입니다.

 

 

그런데, 공식 문서를 보신 분이라면 한 가지 의문이 있습니다. Set 인터페이스에 나와있던 각종 메소드를 HashSet이 구현하여 사용하고 있는 것은 맞지만, equals()와 hashCode()는 보이지 않습니다. 이것들은 어디 간 것일까요??

 

바로, AbstractSet이라는 추상 클래스의 상속을 받는 것이었습니다.

 

 

 

 

그리고 Set 구현 클래스들은 대부분 이 추상 클래스의 상속을 받으므로 각 클래스마다 따로 equals(), hashCode(), removeAll()을 구현해 줄 필요가 없습니다.

 

 

마지막으로, HashSet의 일부 코드를 보겠습니다.

 

 

 

 

이것은 HashMap의 필드인데, HashMap과 PRESENT를 사용하는 것을 알 수 있습니다. 

 

 

 

 

그리고 이 map의 내장 메소드와 PRESENT를 사용하여 HashSet의 다양한 메소드를 정의합니다. PRESENT는 더미 데이터로 map에 value를 넣어 주기 위하여 어쩔 수 없이 이용하는 것이라고 보면 되겠습니다. 즉, HashSet은 Map의 Key만 사용하고 Value는 버리는 방식으로 구현되어있습니다.

 

또한, 아래에서 말씀드릴 LinkedHashSet, TreeSet도 HashSet와 마찬가지로 Map의 Key만 사용하는 방식으로 구현되어있습니다.

 

 

LinkedHashSet Class

HashSet의 상속을 받았으며, 입력된 순서대로 요소를 저장한다는 특징이 있습니다.

 

 

 

 

위 사진은 LinkedHashSet의 생성자를 나타낸 것인데, HashSet과는 달리 내부적으로 LinkedHashMap 인스턴스를 이용하여 요소를 저장한다고 나와있습니다. 요소를 삽입하는 순서대로 순서를 유지하는 마술은 LinkedHashMap을 알아야 이해할 수 있을 것입니다.

 

 

SortedSet Interface

SortedSet 인터페이스는 특정 정렬 기준에 따라 요소의 순서를 정할 수 있습니다.

 

 

 

 

위 사진은 SortedSet의 메소드인데, comparator()을 통해 요소를 정렬해 주는 것을 알 수 있습니다. 또는 Comparable의 상속을 받아서 compareTo()를 재정의하고 있는 객체를 요소로 사용해야합니다. 나머지 메소드는 Set의 일부분을 반환하는 것이라서 쉽게 이해하실 수 있을 것입니다.

 

 

TreeSet Class

TreeSet 클래스는 SortedSet 인터페이스의 대표적인 구현 클래스입니다. SortedSet 인터페이스를 바로 상속받는 것은 아니고, SortedSet 인터페이스를 상속받은 NavigableSet을 상속받습니다. NavigableSet은 SortedSet에 비해 좀더 순회할 수 있는 메소드가 더 많아졌고, TreeMap에 의해 구현되어있다고 나와있습니다. 따라서, TreeMap을 알아야 TreeSet 클래스도 이해가 가능합니다.

 

 

 

 

실제로 TreeSet의 생성자를 보면 TreeMap의 인스턴스를 사용합니다.

 

그리고 간단히 말씀드리자면, TreeSet과 TreeMap은 둘다 레드-블랙 트리로 구현이 되어있습니다. 이를 이용하여 원하는 정렬 기준으로 요소의 순서를 저장할 수 있습니다.

 

 

정리

지금까지 Set 인터페이스를 알아보았습니다. 흥미로운 점은 몇몇 Set의 구현 클래스가 Map의 구현 클래스에서 기반하였다는 것입니다. 그리고 오늘 다룬 HashSet, LinkedHashSet, TreeSet이 모두 그러하였습니다. 따라서 다음 Map 포스팅을 꼭 읽어보셔야합니다.

 

 

출처

 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com

 

 

 

[Java] 자바의 자료구조 - Set(HashSet), Queue(LinkedList) - Onsil's blog

초짜 개발자 온실의
스터디 블로그

onsil-thegreenhouse.github.io

 

댓글

추천 글