일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 안드로이드 레트로핏 crud
- 안드로이드 라이선스 종류
- rxjava disposable
- 플러터 설치 2022
- 객체
- 서비스 vs 쓰레드
- android retrofit login
- 스택 자바 코드
- 서비스 쓰레드 차이
- rxjava cold observable
- 안드로이드 유닛 테스트 예시
- 멤버변수
- 2022 플러터 설치
- 안드로이드 유닛테스트란
- ANR이란
- 스택 큐 차이
- 안드로이드 os 구조
- 2022 플러터 안드로이드 스튜디오
- rxjava hot observable
- 안드로이드 레트로핏 사용법
- jvm 작동 원리
- jvm이란
- 자바 다형성
- 안드로이드 유닛 테스트
- 큐 자바 코드
- 클래스
- 안드로이드 라이선스
- Rxjava Observable
- android ar 개발
- ar vr 차이
- Today
- Total
나만을 위한 블로그
[DS] Set이란? HashSet, TreeSet, LinkedHashSet 사용법 정리 본문
[DS] Set이란? HashSet, TreeSet, LinkedHashSet 사용법 정리
참깨빵위에참깨빵_ 2021. 11. 6. 21:10Set의 사전적 정의는 아래와 같다.
(두 개 이상의 물건으로 된) 한 조(組)
최소한 둘 이상의 것이 하나로 뭉쳤단 뜻이다. 위키백과에선 Set을 아래와 같이 말한다.
https://en.wikipedia.org/wiki/Set_(abstract_data_type)
Set은 특별한 순서 없이 고유한 값을 저장할 수 있는 추상 자료구조다. 유한 집합의 수학적 개념을 컴퓨터로 구현한 것이다. 대부분의 다른 컬렉션 유형과 달리 집합에서 특정 요소를 검색하는 대신 일반적으로 집합의 구성원 자격에 대한 값을 테스트한다. 일부 집합 자료구조는 구성된 후 변경되지 않는 고정 집합 또는 고정 집합을 위해 설계됐다. 정적 집합은 주어진 값이 집합에 있는지 확인하거나, 랜덤하게 값을 열거하는 것과 같은 요소에 대한 쿼리 작업만 허용한다. 동적 또는 변경 가능한 집합(mutable set)이라 하는 다른 변형을 사용하면 집합에서 요소를 삽입, 삭제할 수도 있다. 다중 집합(multiset)은 요소가 여러 번 나타낼 수 있는 특별한 집합이다
고유한 값을 저장한다면 중복되는 값은 집어넣을 수 없단 것 같다.
Set에 대해 설명하는 다른 글을 찾아봤다.
https://www.codejava.net/java-core/collections/java-set-collection-tutorial-and-examples
Set은 중복 요소를 허용하지 않는 컬렉션 유형이다. 즉 요소는 Set에서 한 번만 존재할 수 있다. 수학에서 Set 추상화를 모델링한다. Set의 특징은 아래와 같다.
- 중복 요소를 허용하지 않는다
- 요소는 순서대로 저장되지 않는다. 즉, Set의 요소를 반복할 때 어떤 순서로든 정렬된 요소를 기대할 수 없다.
Set은 아래 경우에 사용한다.
- 중복 또는 고유한 요소 없이 요소를 뚜렷하게 저장할 때
- 요소의 순서를 신경 쓰지 않을 때
예를 들어 Set을 써서 고유한 정수를 저장하거나 카드 게임에서 카드를 무작위로 저장할 수 있다
Set은 List와 다르게 객체(데이터)를 중복 저장할 수 없다. 또한 저장된 객체(데이터)를 인덱스로 관리하지 않기 때문에 저장 순서가 보관되지 않는다. 수학의 집합과 비슷하다. Set 컬렉션을 구현한 대표적인 클래스는 HashSet, TreeSet, LinkedHashSet 등이 있다. Set 컬렉션을 구현하는 클래스들이 공통적으로 쓰는 주요 메서드는 add, iterator, size, remove, clear 등이 있다. Set은 인덱스로 객체(데이터)를 관리하지 않기 때문에 데이터를 검색하려면 iterator()로 iterator(반복자)를 만들고 데이터를 가져와야 한다.
Set을 구현한 자바 소스를 찾지 못해서 자바에서 제공하는 Set 인터페이스를 사용해 HashSet, TreeSet, LinkedHashSet의 사용법을 정리하는 것으로 대신한다. 사용하는 메서드는 위에서 말한 add, addAll, iterator, size, remove, clear만 사용한다.
먼저 HashSet 사용법은 아래와 같다.
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class SetPrac {
public static void main(String[] args) {
Set<Object> set = new HashSet<>();
Set<Object> set2 = new HashSet<>(10);
// loadFactor : 부하율. 용량이 자동으로 증가하기 전 HashSet이 얼마나 가득차게 허용하는지를 규정한다. 기본값은 75%
Set<Object> set3 = new HashSet<>(10, 0.5f);
Set<Object> set4 = new HashSet<>(Arrays.asList(100, 200, 300));
/* add() 사용 */
set.add(1);
set.add(2);
set.add(3);
System.out.println(set);
set2.add(4);
set2.add(5);
set2.add(6);
/* addAll() 사용 : 매개변수로 받은 Set을 메서드 호출객체인 Set 안에 넣는다 */
set.addAll(set2);
System.out.println(set);
/* iterator() 사용 - for문으로 iterator 활용 */
Iterator<Object> iterator = set.iterator();
for (int i = 0; i < set.size(); i++) {
System.out.println("for iterator : " + iterator.next());
}
/* while문으로 iterator 활용 */
while (iterator.hasNext()) {
System.out.println("while iterator : " + iterator.next());
}
/* size() 사용 */
System.out.println("set.size() : " + set.size());
/* remove() 사용 */
set.remove(6);
System.out.println("set.remove(1) 후 : " + set);
/* clear() 사용 */
set.clear();
System.out.println("set.clear() 후 : " + set);
}
}
Set의 선언은 저렇게 다양하게 할 수 있는데, 0.5f를 넣어서 선언한 경우는 Set의 초기용량을 지정한 것이다.
왜냐면 List처럼 Set도 값이 추가되면 저장공간을 늘리는데 한 칸씩 늘리는 게 아니라 2배로 저장용량을 늘리기 때문이라고 한다. 출처는 아래다.
https://coding-factory.tistory.com/554
또한 인덱스가 없기 때문에 당연히 get()도 없어서 반복문과 iterator()를 활용해 Set 안의 값들을 가져와야 한다.
아래 링크는 Set에 대해 설명하는 자바 독스 페이지다.
https://docs.oracle.com/javase/8/docs/api/java/util/Set.html
다음은 TreeSet이다. 위키백과엔 설명이 너무 적게 되어 있어서 다른 사람들은 TreeSet을 어떻게 말하는지 찾아봤다.
https://www.tutorialspoint.com/java/java_treeset_class.htm
TreeSet은 저장을 위해 트리를 사용하는 Set 인터페이스의 구현을 제공한다. 객체는 정렬된 오름차순으로 저장된다. 접근, 검색 시간이 매우 빠르기 때문에 신속하게 찾아야 하는 정렬된 정보를 대량 저장할 때 TreeSet이 좋다.
TreeSet 클래스 역시 Set 인터페이스를 구현한 클래스다. Set 인터페이스를 구현했기 때문에 데이터를 중복해 저장하지 않고, 저장 순서를 유지하지 않는다.
해시코드를 써서 내부 해시 테이블에 데이터를 저장하는 HashSet과 달리 TreeSet은 내부에 데이터 저장을 위한 Red/Black Tree 자료구조를 갖고 있다. RB 트리는 이진 탐색 트리(Binary Search Tree)의 일종으로 저장된 값들이 트리 전체에 골고루 저장되게 해서 비정상적으로 트리 높이가 높아지는 현상이 없게 만든 균형 트리(Balanced Tree)다. 내부에 RB 트리를 써서 값을 저장하기 때문에 현재까지 저장된 값 중 최소값 혹은 최대값을 출력할 수 있고 특정 값보다 큰 값을 빠르게 찾아낼 수 있다. 삽입과 삭제 연산에서 RB 트리의 밸런스를 맞추는 동작이 호출되어 약간의 성능 손해를 보면서 탐색에서의 이점을 가져간 자료구조다
https://devlog-wjdrbs96.tistory.com/108
TreeSet이란?
- Set 인터페이스를 구현한 클래스(중복x, 순서x, 정렬저장o)
- 이진 트리(Binary Tree) 구조
- 데이터 추가, 삭제 시마다 이진 트리 구조를 유지해야 해서 시간이 걸림(검색에 유리)
Red-Black Tree와 이진 트리라는 키워드가 나오는데, 이것은 나중에 알아보고 TreeSet의 사용법을 예제 코드로 확인해본다. 마찬가지로 add, addAll, iterator, size, remove, clear()를 위주로 확인한다.
import java.util.Arrays;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class TreeSetPrac {
public static void main(String[] args) {
Set<Object> set = new TreeSet<>();
Set<Object> set2 = new TreeSet<>(Arrays.asList(7, 8, 9));
/* add() 사용 */
set.add(3);
set.add(1);
set.add(2);
System.out.println(set); // [1, 2, 3]
System.out.println(set2); // [7, 8, 9]
set2.add(4);
set2.add(5);
set2.add(6);
/* addAll() 사용 */
set.addAll(set2);
System.out.println(set); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
/* iterator() 사용 - for문으로 iterator 활용 */
Iterator<Object> iterator = set.iterator();
for (int i = 0; i < set.size(); i++) {
System.out.println("for iterator : " + iterator.next());
}
System.out.println("================================");
/* for-each문으로 iterator 활용 */
for (Object o : set) {
System.out.println("for-each iterator : " + o);
}
/* while문으로 iterator 활용 */
Iterator<Object> iterator2 = set.iterator();
while (iterator2.hasNext()) {
System.out.println("while iterator : " + iterator2.next());
}
/* size() 사용 */
System.out.println("set.size() : " + set.size());
/* remove() 사용 */
set.remove(1);
System.out.println("set.remove(1) 후 : " + set);
/* clear() 사용 */
set.clear();
System.out.println("set.clear() 후 : " + set);
}
}
특이하게도 3, 1, 2 순으로 TreeSet에 추가했는데 출력해보면 1, 2, 3 순서대로 출력되는 걸 볼 수 있다.
이는 TreeSet이 기본적으로 오름차순으로 데이터를 정렬하는 특징이 있기 때문이다.
마지막으로 LinkedHashSet이다.
https://www.tutorialspoint.com/java/java_linkedhashset_class.htm
이 클래스는 HashSet을 확장하지만 자체 멤버를 추가하지 않는다. LinkedHashSet은 삽입된 순서대로 집합에 있는 항목의 연결 목록을 유지관리한다. 이것은 Set에 대한 삽입 순서 반복을 허용한다. 즉, 반복자를 써서 LinkedHashSet을 순환할 때 요소는 삽입된 순서대로 반환된다. 그 다음 해시 코드는 키와 관련된 데이터가 저장되는 인덱스로 사용된다. 키를 해시코드로 바꾸는 작업은 자동 수행된다.
LinkedHashSet은 괜찮아 보이는 글을 찾지 못해서 바로 예제 코드로 넘어간다.
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
public class LinkedHashSetPrac {
public static void main(String[] args) {
Set<Object> set = new LinkedHashSet<>();
Set<Object> otherSet = new LinkedHashSet<>(set);
Set<Object> set3 = new LinkedHashSet<>(Arrays.asList(4, 5, 6));
/* add() 사용 */
set.add(3);
set.add(1);
set.add(2);
System.out.println(set); // [3, 1, 2]
System.out.println(set3); // [4, 5, 6]
/* addAll() 사용 */
set.addAll(set3);
System.out.println(set);
/* iterator() 사용 - for문으로 iterator 활용 */
Iterator<Object> iterator = set.iterator();
for (int i = 0; i < set.size(); i++) {
System.out.println("for iterator : " + iterator.next());
}
System.out.println("================================");
/* for-each문으로 iterator 활용 */
for (Object o : set) {
System.out.println("for-each iterator : " + o);
}
/* while문으로 iterator 활용 */
Iterator<Object> iterator2 = set.iterator();
while (iterator2.hasNext()) {
System.out.println("while iterator : " + iterator2.next());
}
/* size() 사용 */
System.out.println("set.size() : " + set.size());
/* remove() 사용 */
set.remove(1);
System.out.println("set.remove(1) 후 : " + set);
/* clear() 사용 */
set.clear();
System.out.println("set.clear() 후 : " + set);
}
}
LinkedHashSet은 TreeSet과 달리 출력 시 입력된 순서대로 데이터를 보여준다.
HashSet, TreeSet, LinkedHashSet을 표로 비교하면 아래와 같다.
이름 | 데이터 중복 여부 | 순서 보장 여부 | 기타 |
HashSet | 데이터 중복 x | 순서 보장 x | - |
TreeSet | 오름차순으로 데이터 정렬 (1~9, a~z) |
||
LinkedHashSet | 입력된 순서대로 데이터 관리 | - |
참고한 사이트)
https://velog.io/@gillog/HashSet
'개인 공부 > Data structure' 카테고리의 다른 글
[DS] 배열이란? 배열 사용법 (Kotlin) (0) | 2023.02.05 |
---|---|
[DS] 그래프란? (0) | 2022.12.21 |
[DS] Linked List(링크드 리스트)란? + 자바 구현 예시 (0) | 2021.11.05 |
[DS] 스택 vs 큐 차이 + 자바 구현 예시(with 배열, ArrayList) (0) | 2021.10.30 |
[DS] Map이란? HashMap 사용법 (0) | 2021.07.01 |