자바의 강력한 도구인 Set
에 대해 배우는 시간입니다. 구조와 원리에 대해서는 “Java로 배우는 자료구조” 코스에서 좀 더 깊게 이해를 하실 수 있습니다. 이 강의에서는 어떤 도구들이 있고 어떤 특징이 있는지, 어떻게 사용하는지에 대해서만 알아봅니다.
ㅤ
ㅤ
Java의 Collection에는 집합(Set)이라는 자료구조가 있습니다. 집합처럼 중복되지 않는 원소들의 모음을 만들 수 있는 자료구조를 Set이라고 합니다.
이러한 Set
의 특징은 집합에 있는 동일한 원소를 저장하더라도 Set
에는 중복된 원소가 존재하지 않는다는 점입니다.
Set의 구조가 왜 필요할까요? 수학과 관련된 일이 아니면 써먹을 일이 없지 않을까요? 라고 생각할 수도 있습니다. 간단한 예시로 고민해 봅시다.
접속 날짜 | 접속 시간 | 아이디 |
---|---|---|
2020-01-01 | 10:00 | roka |
2020-01-01 | 20:00 | 코드라떼 |
2020-01-02 | 13:00 | roka |
2020-01-02 | 13:30 | 코드라떼 |
2020-01-02 | 14:00 | roka |
2020-01-02 | 15:00 | 카페라떼 |
2020-01-02 | 18:00 | 카페라떼 |
해당 표는 특정 아이디가 어떤 서비스에 접속한 날짜와 시간이라고 가정합니다.
그리고 해당 표를 이용하여 우리는 두 가지 문제를 풀어야 한다고 가정합니다.
2020-01-01 ~ 2020-01-02 까지 접속한 아이디의 수
2020-01-01 ~ 2020-01-02 까지 접속한 아이디
이 문제를 어떻게 풀 수 있을까요?
혹시 눈으로 슥~ 보면서 풀고계시진 않으신가요?
이럴 때 Set
구조를 이용하면 간단하게 풀 수 있습니다.
Set
에는 크게 TreeSet
, HashSet
, LinkedHashSet
이 있습니다.
우리는 각 Set
과 관련된 클래스들을 살펴보며 장점과 단점은 무엇인지 그리고 어떤 특징이 있는지 살펴볼 예정입니다.
ㅤ
HashSet
은 데이터 저장을 Hash Table을 이용하는 구조로 저장하는 Set
입니다.
Set
의 특징을 가지고 있으며, 동일한 원소를 저장하더라도 저장소에 중복된 값이 존재하지 않습니다.
HashSet
은 HashTable 구조를 이용한 HashMap
을 이용하여 만들어져 있습니다.
// HashSet의 생성자
public HashSet() {
map = new HashMap<>();
}
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size() / 0.75f) + 1, 16));
}
…
HashSet
의 생성자를 보면 HashMap
을 이용하여 Set
구조를 만드는 것을 확인할 수 있습니다.
// 더미 Object
public static final Object PRESENT = new Object();
// HashSet의 데이터 add 메서드
public boolean add(E e) {
return map.put(e, PRESENT) == null;
}
Map
의 특성 중 하나인 중복 key는 존재할 수 없다는 특징을 이용하여, key를 Set
의 값으로, value에는 더미 Object
를 저장 방식으로 데이터를 추가합니다.
즉, HashSet
을 이해하려면 HashMap
에 대해서 먼저 알아야 합니다.
ㅤ
Hash Table 구조 기반이다.
HashMap을 이용하여 구현되므로, HashMap의 장점과 특징을 그대로 계승한다.
ㅤ
index가 아닌 key를 이용하여 데이터 저장과 접근이 필요할 경우 사용한다.
데이터의 크기가 어느 정도 예상되는 경우 사용한다.
삽입 삭제가 빈번할 경우 사용한다.
ㅤ
import java.util.HashSet;
HashSet<String> texts = new HashSet<>();
ㅤ
import java.util.HashSet;
// String value
HashSet<String> set = new HashSet<>();
// 데이터 삽입
set.add("코드라떼");
set.add("codelatte");
HashSet.add(value)
메서드를 이용하여 데이터를 저장할 수 있습니다.
ㅤ
import java.util.HashSet;
// String value
HashSet<String> set = new HashSet<>();
// 데이터 삽입
set.add("코드라떼");
set.add("codelatte");
boolean isExist = set.contains("codelatte");
// 있으면 true, 없으면 false
ㅤ
import java.util.HashSet;
// String value
HashSet<String> set = new HashSet<>();
// 데이터 삽입
set.add("코드라떼");
set.add("codelatte");
set.add("카페라떼");
// 데이터 삭제
set.remove("카페라떼");
ㅤ
import java.util.HashSet;
// String value
HashSet<String> set = new HashSet<>();
// 데이터 삽입
set.add("1");
set.add("23");
set.add("2");
set.add("14");
set.add("2");
set.add("5");
for (String value : set) {
System.out.println(value);
}
// "1", "23", "2", "14", "5"
HashMap
을 이용하여 만들어졌으므로, 저장된 값은 정렬되어 있지 않습니다.
ㅤ
TreeSet
은 논리적인 Tree 구조로 데이터를 저장하는 Set
입니다.
Set
의 특징을 가지고 있으며, 동일한 원소를 저장하더라도 저장소에는 중복된 값이 존재하지 않습니다.
또한 TreeSet
은 Tree 구조를 이용한 TreeMap
을 이용하여 만들어져 있습니다.
// TreeSet의 생성자
public TreeSet() {
this(new TreeMap<E, Object>());
}
…
TreeSet
의 생성자를 보면 TreeMap
을 이용하여 Set
구조를 만드는 것을 확인할 수 있습니다.
// 더미 Object
public static final Object PRESENT = new Object();
// TreeSet의 데이터 add 메서드
public boolean add(E e) {
return m.put(e, PRESENT) == null;
}
Map
의 특성 중 하나인 중복 key는 존재할 수 없다는 특징을 이용하여, key를 Set
의 값으로, value에는 더미 Object
를 저장 방식으로 데이터를 추가합니다.
즉, TreeSet
을 이해하려면 TreeMap
에 대해서 먼저 알아야 합니다.
ㅤ
Tree 구조 기반이다.
TreeMap을 이용하여 구현되므로, TreeMap의 장점과 특징을 그대로 계승한다.
ㅤ
저장되는 데이터의 개수가 몇 개인지 예상되지 않는 경우 사용한다.
삽입과 삭제가 빈번하지 않을 때 사용한다.
정렬된 값이 필요할 때 사용한다.
ㅤ
import java.util.TreeSet;
TreeSet<String> texts = new TreeSet<>();
ㅤ
import java.util.TreeSet;
// String value
TreeSet<String> set = new TreeSet<>();
// 데이터 삽입
set.add("codelatte");
set.add("코드라떼");
TreeSet.add(value)
메서드를 이용하여 데이터를 저장할 수 있습니다.
ㅤ
import java.util.TreeSet;
// String value
TreeSet<String> set = new TreeSet<>();
// 데이터 삽입
set.add("codelatte");
set.add("코드라떼");
boolean isExist = set.contains("코드라떼");
// 있으면 true, 없으면 false
ㅤ
import java.util.TreeSet;
// String value
TreeSet<String> set = new TreeSet<>();
// 데이터 삽입
set.add("codelatte");
set.add("코드라떼");
// 데이터 삭제
set.remove("코드라떼");
ㅤ
import java.util.TreeSet;
// String value
TreeSet<String> set = new TreeSet<>();
// 데이터 삽입
set.add("1");
set.add("3");
set.add("2");
set.add("4");
set.add("2");
set.add("5");
for (String value : set) {
System.out.println(value);
}
// "1", "2", "3", "4", "5"
TreeMap
을 이용하여 만들어졌으므로, 저장된 값은 오름차순으로 정렬되어 출력할 수 있습니다.
ㅤ
LinkedHashSet
은 HashSet
을 상속하여 만들어진 클래스입니다.
그러므로 HashSet
의 특징을 가지고 있습니다.
// LinkedHashSet은 HashSet을 상속 받는다
public LinkedHashSet<E> extends HashSet<E> …
// LinkedHashSet의 생성자
public LinkedHashSet() {
super(16, .75f, true);
}
LinkedHashSet
의 생성자를 보면 HashSet
을 상속받은 것을 확인할 수 있습니다.
다만 주의할 점은 super
키워드를 사용하여 호출할 때, HashSet
의 default 접근 제어 지시자의 생성자를 호출합니다.
// HashSet의 default 접근 제어 지시자 생성자
HashSet(int initialCapacity, float loadFactor, boolean dummy {
map = new LinkedHashMap<>(initialCapacity, loadFactor)
}
HashSet
에는 LinkedHashMap
을 이용하는 코드가 작성되어있습니다.
즉 정리하면, HashSet
클래스에는 기본적으로는 HashMap
을 이용하도록 구현되어 있으나 HashSet
클래스를 상속받아 구현할 때는, java.util 패키지 내에서 default 접근 제어 지시자로 작성된 HashSet
생성자를 super
키워드를 이용하여 호출 가능하기 때문에 LinkedHashMap
으로 사용할 수 있도록 구현되어 있습니다.
ㅤ
HashSet을 상속받아 구현되나, LinkedHashMap을 이용하며 LinkedHashMap의 특징을 그대로 계승한다.
ㅤ
값의 저장된 순서가 중요할 때 사용한다.
ㅤ
import java.util.LinkedHashSet;
LinkedHashSet<String> texts = new LinkedHashSet<>();
ㅤ
import java.util.LinkedHashSet;
// String value
LinkedHashSet<String> set = new LinkedHashSet<>();
// 데이터 삽입
set.add("codelatte");
set.add("코드라떼");
LinkedHashSet.add(value)
메서드를 이용하여 데이터를 저장할 수 있습니다.
ㅤ
import java.util.LinkedHashSet;
// String value
LinkedHashSet<String> set = new LinkedHashSet<>();
// 데이터 삽입
set.add("codelatte");
set.add("코드라떼");
boolean isExist = set.contains("roka");
// 있으면 true, 없으면 false
ㅤ
import java.util.LinkedHashSet;
// String value
LinkedHashSet<String> set = new LinkedHashSet<>();
// 데이터 삽입
set.add("codelatte");
set.add("코드라떼");
set.add("카페라떼");
// 데이터 삭제
set.remove("카페라떼");
ㅤ
import java.util.LinkedHashSet;
// String value
LinkedHashSet<String> set = new LinkedHashSet<>();
// 데이터 삽입
set.add("1");
set.add("23");
set.add("3");
set.add("14");
set.add("2");
set.add("5");
for (String value : set) {
System.out.println(value);
}
// "1", "23", "3", "14", "2", "5"
LinkedHashMap
을 이용하므로, 저장된 값은 저장된 순서대로 출력됩니다.
ㅤ
추가적으로 합집합, 교집합, 차집합, 여집합, 부분집합을 연산하거나 확인하고 싶을 때 보시면 됩니다.
지금 당장 필요하지 않다면 후 순위로 미뤄두시는 것이 낫습니다.
세 개의 집합이 존재합니다.
A = {1, 2, 3, 4, 5}
B = {3, 4, 5, 6, 7}
C = {3, 4}
우리는 Java에서 이 세 개의 집합을 어떻게 표현하며 합집합, 교집합, 차집합, 여집합, 부분집합 여부를 어떻게 연산하는지 확인해볼 예정입니다.
// A 집합
List<String> set1 = Arrays.asList("1", "2", "3", "4", "5");
TreeSet<String> A = new TreeSet<>(set1);
// B 집합
List<String> set2 = Arrays.asList("3", "4", "5", "6", "7");
TreeSet<String> B = new TreeSet<>(set2);
// C 집합
List<String> set3 = Arrays.asList("3", "4");
TreeSet<String> C = new TreeSet<>(set3);
ㅤ
boolean isContainAll = B.containsAll(C);
System.out.println("C ⊂ B ? "+isContainAll);
Set.containsAll(set)
메서드를 이용하여 부분집합 여부를 확인할 수 있습니다.
부분집합이면 true
, 부분집합이 아니면 false
를 반환합니다.
ㅤ
boolean isContain = B.contains("7");
System.out.println("7 ⊂ B ? "+ isContain);
Set.contains(value)
메서드를 이용하여 해당 집합에 원소가 포함되는지 확인할 수 있습니다.
원소가 포함되면 true
, 원소가 포함되지 않으면 false
를 반환합니다.
ㅤ
TreeSet<String> cloneA = new TreeSet<>(set1);
boolean isModified = cloneA.retainAll(B);
System.out.println("A ∩ B ? "+cloneA);
Set.retainAll(collection)
메서드를 이용하여 교집합을 추출할 수 있습니다.
반환값은 cloneA 변경 여부를 반환합니다.
cloneA에 원소가 존재하지 않는 경우를 제외하고는 항상 true
를 반환한다고 보시면 됩니다.
그리고 Set.retainAll(collection)
메서드는 원본의 데이터를 변경하므로, 원본의 데이터 손실을 원하지 않는다면 원본을 복사해서 사용해야 합니다.
ㅤ
TreeSet<String> cloneA = new TreeSet<>(set1);
boolean isModified = cloneA.addAll(B);
System.out.println("A ∪ B ? "+cloneA);
Set.addAll(collection)
메서드를 이용하여 합집합을 추출할 수 있습니다.
반환값은 cloneA 변경 여부를 반환합니다.
cloneA에 원소가 존재하지 않는 경우를 제외하고는 항상 true
를 반환한다고 보시면 됩니다.
그리고 Set.addAll(collection)
메서드는 원본의 데이터를 변경하므로, 원본의 데이터 변경을 원하지 않는다면 원본을 복사해서 사용해야 합니다.
ㅤ
TreeSet<String> cloneA = new TreeSet<>(set1);
boolean isModified = cloneA.removeAlll(B);
System.out.println("A - B ? "+cloneA);
Set.removeAll(collection)
메서드를 이용하여 차집합을 추출할 수 있습니다.
반환값은 cloneA 변경 여부를 반환합니다.
cloneA에 원소가 존재하지 않는 경우를 제외하고는 항상 true
를 반환한다고 보시면 됩니다.
그리고 Set.removeAll(collection)
메서드는 원본의 데이터를 변경하므로, 원본의 데이터 변경을 원하지 않는다면 원본을 복사해서 사용해야 합니다.
실습도구에서 합집합, 교집합, 차집합은 구현에 문제가 없지만, 나머지 3개는 각각의 주석만 풀고 실행시켰을 때 에러가 나옵니다. (코드의 다른 부분을 수정하지 않았습니다.) 확인을 부탁드립니다.
안녕하세요. 코드라떼입니다 :) 패키지가 import되지 않아서 발생한 문제로 import 구문을 추가한 코드를 업로드했습니다. 감사합니다 :)
'LinkedHashSet값 출력'부분에서 마지막 결과 값 순서가 1 23 3 14 2 5 인건가요? 저장된 순서대로 출력되는거니까
안녕하세요. 코드라떼입니다 :) "1" "23" "3" "14" "2" "5"가 맞습니다. 뭐라 드릴 말씀이 없군요.. 감사합니다! ps. 추가로 넬준님 메일로 프로모션 코드를 제공해드렸습니다. 확인 부탁드립니다. 감사합니다 :)
추가노트 마지막 문단에 아래와 같이 써있는데, 오타가 있어요! /* Set.removeAll(collection) 메서드를 이용하여 합집합을 추출할 수 있습니다. 반환값은 cloneA 변경 여부를 반환합니다. cloneA에 원소가 존재하지 않는 경우를 제외하고는 항상 true를 반환한다고 보시면 됩니다. 그리고 Set.addAll(collection) 메서드는 원본의 데이터를 변경하므로, 원본의 데이터 변경을 원하지 않는다면 원본을 복사해서 사용해야 합니다. */ 첫번째 줄 : 합집합 -> 차집합 마지막 줄 : Set.addAll(collection) -> Set.removeAll(collection)
자바배움이님 감사합니다.^^ 수정했습니다. ps.자바배움이 님이 꼼꼼하게 공부하시는 것에 감명 깊어 이후에 나올 코스를 무료로 수강하실 수 있도록 출시 후에 별도로 연락드리겠습니다.^^
자바의 강력한 도구인 Set
에 대해 배우는 시간입니다. 구조와 원리에 대해서는 “Java로 배우는 자료구조” 코스에서 좀 더 깊게 이해를 하실 수 있습니다. 이 강의에서는 어떤 도구들이 있고 어떤 특징이 있는지, 어떻게 사용하는지에 대해서만 알아봅니다.
ㅤ
ㅤ
Java의 Collection에는 집합(Set)이라는 자료구조가 있습니다. 집합처럼 중복되지 않는 원소들의 모음을 만들 수 있는 자료구조를 Set이라고 합니다.
이러한 Set
의 특징은 집합에 있는 동일한 원소를 저장하더라도 Set
에는 중복된 원소가 존재하지 않는다는 점입니다.
Set의 구조가 왜 필요할까요? 수학과 관련된 일이 아니면 써먹을 일이 없지 않을까요? 라고 생각할 수도 있습니다. 간단한 예시로 고민해 봅시다.
접속 날짜 | 접속 시간 | 아이디 |
---|---|---|
2020-01-01 | 10:00 | roka |
2020-01-01 | 20:00 | 코드라떼 |
2020-01-02 | 13:00 | roka |
2020-01-02 | 13:30 | 코드라떼 |
2020-01-02 | 14:00 | roka |
2020-01-02 | 15:00 | 카페라떼 |
2020-01-02 | 18:00 | 카페라떼 |
해당 표는 특정 아이디가 어떤 서비스에 접속한 날짜와 시간이라고 가정합니다.
그리고 해당 표를 이용하여 우리는 두 가지 문제를 풀어야 한다고 가정합니다.
2020-01-01 ~ 2020-01-02 까지 접속한 아이디의 수
2020-01-01 ~ 2020-01-02 까지 접속한 아이디
이 문제를 어떻게 풀 수 있을까요?
혹시 눈으로 슥~ 보면서 풀고계시진 않으신가요?
이럴 때 Set
구조를 이용하면 간단하게 풀 수 있습니다.
Set
에는 크게 TreeSet
, HashSet
, LinkedHashSet
이 있습니다.
우리는 각 Set
과 관련된 클래스들을 살펴보며 장점과 단점은 무엇인지 그리고 어떤 특징이 있는지 살펴볼 예정입니다.
ㅤ
HashSet
은 데이터 저장을 Hash Table을 이용하는 구조로 저장하는 Set
입니다.
Set
의 특징을 가지고 있으며, 동일한 원소를 저장하더라도 저장소에 중복된 값이 존재하지 않습니다.
HashSet
은 HashTable 구조를 이용한 HashMap
을 이용하여 만들어져 있습니다.
// HashSet의 생성자
public HashSet() {
map = new HashMap<>();
}
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size() / 0.75f) + 1, 16));
}
…
HashSet
의 생성자를 보면 HashMap
을 이용하여 Set
구조를 만드는 것을 확인할 수 있습니다.
// 더미 Object
public static final Object PRESENT = new Object();
// HashSet의 데이터 add 메서드
public boolean add(E e) {
return map.put(e, PRESENT) == null;
}
Map
의 특성 중 하나인 중복 key는 존재할 수 없다는 특징을 이용하여, key를 Set
의 값으로, value에는 더미 Object
를 저장 방식으로 데이터를 추가합니다.
즉, HashSet
을 이해하려면 HashMap
에 대해서 먼저 알아야 합니다.
ㅤ
Hash Table 구조 기반이다.
HashMap을 이용하여 구현되므로, HashMap의 장점과 특징을 그대로 계승한다.
ㅤ
index가 아닌 key를 이용하여 데이터 저장과 접근이 필요할 경우 사용한다.
데이터의 크기가 어느 정도 예상되는 경우 사용한다.
삽입 삭제가 빈번할 경우 사용한다.
ㅤ
import java.util.HashSet;
HashSet<String> texts = new HashSet<>();
ㅤ
import java.util.HashSet;
// String value
HashSet<String> set = new HashSet<>();
// 데이터 삽입
set.add("코드라떼");
set.add("codelatte");
HashSet.add(value)
메서드를 이용하여 데이터를 저장할 수 있습니다.
ㅤ
import java.util.HashSet;
// String value
HashSet<String> set = new HashSet<>();
// 데이터 삽입
set.add("코드라떼");
set.add("codelatte");
boolean isExist = set.contains("codelatte");
// 있으면 true, 없으면 false
ㅤ
import java.util.HashSet;
// String value
HashSet<String> set = new HashSet<>();
// 데이터 삽입
set.add("코드라떼");
set.add("codelatte");
set.add("카페라떼");
// 데이터 삭제
set.remove("카페라떼");
ㅤ
import java.util.HashSet;
// String value
HashSet<String> set = new HashSet<>();
// 데이터 삽입
set.add("1");
set.add("23");
set.add("2");
set.add("14");
set.add("2");
set.add("5");
for (String value : set) {
System.out.println(value);
}
// "1", "23", "2", "14", "5"
HashMap
을 이용하여 만들어졌으므로, 저장된 값은 정렬되어 있지 않습니다.
ㅤ
TreeSet
은 논리적인 Tree 구조로 데이터를 저장하는 Set
입니다.
Set
의 특징을 가지고 있으며, 동일한 원소를 저장하더라도 저장소에는 중복된 값이 존재하지 않습니다.
또한 TreeSet
은 Tree 구조를 이용한 TreeMap
을 이용하여 만들어져 있습니다.
// TreeSet의 생성자
public TreeSet() {
this(new TreeMap<E, Object>());
}
…
TreeSet
의 생성자를 보면 TreeMap
을 이용하여 Set
구조를 만드는 것을 확인할 수 있습니다.
// 더미 Object
public static final Object PRESENT = new Object();
// TreeSet의 데이터 add 메서드
public boolean add(E e) {
return m.put(e, PRESENT) == null;
}
Map
의 특성 중 하나인 중복 key는 존재할 수 없다는 특징을 이용하여, key를 Set
의 값으로, value에는 더미 Object
를 저장 방식으로 데이터를 추가합니다.
즉, TreeSet
을 이해하려면 TreeMap
에 대해서 먼저 알아야 합니다.
ㅤ
Tree 구조 기반이다.
TreeMap을 이용하여 구현되므로, TreeMap의 장점과 특징을 그대로 계승한다.
ㅤ
저장되는 데이터의 개수가 몇 개인지 예상되지 않는 경우 사용한다.
삽입과 삭제가 빈번하지 않을 때 사용한다.
정렬된 값이 필요할 때 사용한다.
ㅤ
import java.util.TreeSet;
TreeSet<String> texts = new TreeSet<>();
ㅤ
import java.util.TreeSet;
// String value
TreeSet<String> set = new TreeSet<>();
// 데이터 삽입
set.add("codelatte");
set.add("코드라떼");
TreeSet.add(value)
메서드를 이용하여 데이터를 저장할 수 있습니다.
ㅤ
import java.util.TreeSet;
// String value
TreeSet<String> set = new TreeSet<>();
// 데이터 삽입
set.add("codelatte");
set.add("코드라떼");
boolean isExist = set.contains("코드라떼");
// 있으면 true, 없으면 false
ㅤ
import java.util.TreeSet;
// String value
TreeSet<String> set = new TreeSet<>();
// 데이터 삽입
set.add("codelatte");
set.add("코드라떼");
// 데이터 삭제
set.remove("코드라떼");
ㅤ
import java.util.TreeSet;
// String value
TreeSet<String> set = new TreeSet<>();
// 데이터 삽입
set.add("1");
set.add("3");
set.add("2");
set.add("4");
set.add("2");
set.add("5");
for (String value : set) {
System.out.println(value);
}
// "1", "2", "3", "4", "5"
TreeMap
을 이용하여 만들어졌으므로, 저장된 값은 오름차순으로 정렬되어 출력할 수 있습니다.
ㅤ
LinkedHashSet
은 HashSet
을 상속하여 만들어진 클래스입니다.
그러므로 HashSet
의 특징을 가지고 있습니다.
// LinkedHashSet은 HashSet을 상속 받는다
public LinkedHashSet<E> extends HashSet<E> …
// LinkedHashSet의 생성자
public LinkedHashSet() {
super(16, .75f, true);
}
LinkedHashSet
의 생성자를 보면 HashSet
을 상속받은 것을 확인할 수 있습니다.
다만 주의할 점은 super
키워드를 사용하여 호출할 때, HashSet
의 default 접근 제어 지시자의 생성자를 호출합니다.
// HashSet의 default 접근 제어 지시자 생성자
HashSet(int initialCapacity, float loadFactor, boolean dummy {
map = new LinkedHashMap<>(initialCapacity, loadFactor)
}
HashSet
에는 LinkedHashMap
을 이용하는 코드가 작성되어있습니다.
즉 정리하면, HashSet
클래스에는 기본적으로는 HashMap
을 이용하도록 구현되어 있으나 HashSet
클래스를 상속받아 구현할 때는, java.util 패키지 내에서 default 접근 제어 지시자로 작성된 HashSet
생성자를 super
키워드를 이용하여 호출 가능하기 때문에 LinkedHashMap
으로 사용할 수 있도록 구현되어 있습니다.
ㅤ
HashSet을 상속받아 구현되나, LinkedHashMap을 이용하며 LinkedHashMap의 특징을 그대로 계승한다.
ㅤ
값의 저장된 순서가 중요할 때 사용한다.
ㅤ
import java.util.LinkedHashSet;
LinkedHashSet<String> texts = new LinkedHashSet<>();
ㅤ
import java.util.LinkedHashSet;
// String value
LinkedHashSet<String> set = new LinkedHashSet<>();
// 데이터 삽입
set.add("codelatte");
set.add("코드라떼");
LinkedHashSet.add(value)
메서드를 이용하여 데이터를 저장할 수 있습니다.
ㅤ
import java.util.LinkedHashSet;
// String value
LinkedHashSet<String> set = new LinkedHashSet<>();
// 데이터 삽입
set.add("codelatte");
set.add("코드라떼");
boolean isExist = set.contains("roka");
// 있으면 true, 없으면 false
ㅤ
import java.util.LinkedHashSet;
// String value
LinkedHashSet<String> set = new LinkedHashSet<>();
// 데이터 삽입
set.add("codelatte");
set.add("코드라떼");
set.add("카페라떼");
// 데이터 삭제
set.remove("카페라떼");
ㅤ
import java.util.LinkedHashSet;
// String value
LinkedHashSet<String> set = new LinkedHashSet<>();
// 데이터 삽입
set.add("1");
set.add("23");
set.add("3");
set.add("14");
set.add("2");
set.add("5");
for (String value : set) {
System.out.println(value);
}
// "1", "23", "3", "14", "2", "5"
LinkedHashMap
을 이용하므로, 저장된 값은 저장된 순서대로 출력됩니다.
ㅤ
추가적으로 합집합, 교집합, 차집합, 여집합, 부분집합을 연산하거나 확인하고 싶을 때 보시면 됩니다.
지금 당장 필요하지 않다면 후 순위로 미뤄두시는 것이 낫습니다.
세 개의 집합이 존재합니다.
A = {1, 2, 3, 4, 5}
B = {3, 4, 5, 6, 7}
C = {3, 4}
우리는 Java에서 이 세 개의 집합을 어떻게 표현하며 합집합, 교집합, 차집합, 여집합, 부분집합 여부를 어떻게 연산하는지 확인해볼 예정입니다.
// A 집합
List<String> set1 = Arrays.asList("1", "2", "3", "4", "5");
TreeSet<String> A = new TreeSet<>(set1);
// B 집합
List<String> set2 = Arrays.asList("3", "4", "5", "6", "7");
TreeSet<String> B = new TreeSet<>(set2);
// C 집합
List<String> set3 = Arrays.asList("3", "4");
TreeSet<String> C = new TreeSet<>(set3);
ㅤ
boolean isContainAll = B.containsAll(C);
System.out.println("C ⊂ B ? "+isContainAll);
Set.containsAll(set)
메서드를 이용하여 부분집합 여부를 확인할 수 있습니다.
부분집합이면 true
, 부분집합이 아니면 false
를 반환합니다.
ㅤ
boolean isContain = B.contains("7");
System.out.println("7 ⊂ B ? "+ isContain);
Set.contains(value)
메서드를 이용하여 해당 집합에 원소가 포함되는지 확인할 수 있습니다.
원소가 포함되면 true
, 원소가 포함되지 않으면 false
를 반환합니다.
ㅤ
TreeSet<String> cloneA = new TreeSet<>(set1);
boolean isModified = cloneA.retainAll(B);
System.out.println("A ∩ B ? "+cloneA);
Set.retainAll(collection)
메서드를 이용하여 교집합을 추출할 수 있습니다.
반환값은 cloneA 변경 여부를 반환합니다.
cloneA에 원소가 존재하지 않는 경우를 제외하고는 항상 true
를 반환한다고 보시면 됩니다.
그리고 Set.retainAll(collection)
메서드는 원본의 데이터를 변경하므로, 원본의 데이터 손실을 원하지 않는다면 원본을 복사해서 사용해야 합니다.
ㅤ
TreeSet<String> cloneA = new TreeSet<>(set1);
boolean isModified = cloneA.addAll(B);
System.out.println("A ∪ B ? "+cloneA);
Set.addAll(collection)
메서드를 이용하여 합집합을 추출할 수 있습니다.
반환값은 cloneA 변경 여부를 반환합니다.
cloneA에 원소가 존재하지 않는 경우를 제외하고는 항상 true
를 반환한다고 보시면 됩니다.
그리고 Set.addAll(collection)
메서드는 원본의 데이터를 변경하므로, 원본의 데이터 변경을 원하지 않는다면 원본을 복사해서 사용해야 합니다.
ㅤ
TreeSet<String> cloneA = new TreeSet<>(set1);
boolean isModified = cloneA.removeAlll(B);
System.out.println("A - B ? "+cloneA);
Set.removeAll(collection)
메서드를 이용하여 차집합을 추출할 수 있습니다.
반환값은 cloneA 변경 여부를 반환합니다.
cloneA에 원소가 존재하지 않는 경우를 제외하고는 항상 true
를 반환한다고 보시면 됩니다.
그리고 Set.removeAll(collection)
메서드는 원본의 데이터를 변경하므로, 원본의 데이터 변경을 원하지 않는다면 원본을 복사해서 사용해야 합니다.
실습도구에서 합집합, 교집합, 차집합은 구현에 문제가 없지만, 나머지 3개는 각각의 주석만 풀고 실행시켰을 때 에러가 나옵니다. (코드의 다른 부분을 수정하지 않았습니다.) 확인을 부탁드립니다.
안녕하세요. 코드라떼입니다 :) 패키지가 import되지 않아서 발생한 문제로 import 구문을 추가한 코드를 업로드했습니다. 감사합니다 :)
'LinkedHashSet값 출력'부분에서 마지막 결과 값 순서가 1 23 3 14 2 5 인건가요? 저장된 순서대로 출력되는거니까
안녕하세요. 코드라떼입니다 :) "1" "23" "3" "14" "2" "5"가 맞습니다. 뭐라 드릴 말씀이 없군요.. 감사합니다! ps. 추가로 넬준님 메일로 프로모션 코드를 제공해드렸습니다. 확인 부탁드립니다. 감사합니다 :)
추가노트 마지막 문단에 아래와 같이 써있는데, 오타가 있어요! /* Set.removeAll(collection) 메서드를 이용하여 합집합을 추출할 수 있습니다. 반환값은 cloneA 변경 여부를 반환합니다. cloneA에 원소가 존재하지 않는 경우를 제외하고는 항상 true를 반환한다고 보시면 됩니다. 그리고 Set.addAll(collection) 메서드는 원본의 데이터를 변경하므로, 원본의 데이터 변경을 원하지 않는다면 원본을 복사해서 사용해야 합니다. */ 첫번째 줄 : 합집합 -> 차집합 마지막 줄 : Set.addAll(collection) -> Set.removeAll(collection)
자바배움이님 감사합니다.^^ 수정했습니다. ps.자바배움이 님이 꼼꼼하게 공부하시는 것에 감명 깊어 이후에 나올 코스를 무료로 수강하실 수 있도록 출시 후에 별도로 연락드리겠습니다.^^