1. Set์ด๋?
โ๏ธ ์ค๋ณต์ ํ์ฉํ์ง ์๊ณ , ์์๋ฅผ ๋ณด์ฅํ์ง ์๋ ์๋ฃ๊ตฌ์กฐ
โ๏ธ ๋ํ์ ์ธ ๊ตฌํ์ฒด: HashSet, LinkedHashSet, TreeSet
2. Set์ ๊ธฐ๋ณธ ๋์
โ๏ธ add(value) : ์ค๋ณต์ด๋ฉด ์ ์ฅํ์ง ์์
โ๏ธ contains(value) : ํฌํจ ์ฌ๋ถ ํ์ธ
โ๏ธ remove(value) : ๋ฐ์ดํฐ ์ญ์
โน๏ธ ํ์ง๋ง ์ผ๋ฐ์ ์ธ Set ๊ตฌํ์ฒด๋ ๋ด๋ถ ๋ฐ์ดํฐ๋ฅผ ์ผ์ผ์ด ๋น๊ต → ์๊ฐ ๋ณต์ก๋ O(n)
3. HashSet์ด๋?
โ๏ธ ๋ด๋ถ์ ์ผ๋ก ํด์ ํจ์๋ฅผ ์ด์ฉํ ๋ฐฐ์ด ๊ธฐ๋ฐ์ ๊ตฌ์กฐ
โ๏ธ hashCode()์ equals()๋ฅผ ๊ธฐ์ค์ผ๋ก ์ค๋ณต ์ฌ๋ถ๋ฅผ ํ๋จ
โ๏ธ ํ์ ์๋ ๋น ๋ฆ (ํ๊ท ์๊ฐ ๋ณต์ก๋ O(1))
4. ์ง์ ๊ตฌํํ๋ Set - MyHashSetV1 (์ ์ํ ์ ์ฉ)
public class MyHashSetV1 {
static final int DEFAULT_INITIAL_CAPACITY = 16;
LinkedList<Integer>[] buckets; // ๋ฒํท(ํด์ ์ธ๋ฑ์ค๋ณ ์ ์ฅ ๊ณต๊ฐ)
private int size = 0;
private int capacity = DEFAULT_INITIAL_CAPACITY;
public MyHashSetV1() {
initBuckets();
}
public MyHashSetV1(int capacity) {
this.capacity = capacity;
initBuckets();
}
// ๋ฒํท ๋ฐฐ์ด ์ด๊ธฐํ
private void initBuckets() {
buckets = new LinkedList[capacity];
for (int i = 0; i < capacity; i++) {
buckets[i] = new LinkedList<>();
}
}
// ํด์ ์ธ๋ฑ์ค ๊ณ์ฐ
private int hashIndex(int value) {
return value % capacity;
}
public boolean add(int value) {
int hashIndex = hashIndex(value);
LinkedList<Integer> bucket = buckets[hashIndex];
if (bucket.contains(value)) return false;
bucket.add(value);
size++;
return true;
}
public boolean contains(int searchValue) {
int hashIndex = hashIndex(searchValue);
return buckets[hashIndex].contains(searchValue);
}
public boolean remove(int value) {
int hashIndex = hashIndex(value);
boolean removed = buckets[hashIndex].remove(Integer.valueOf(value));
if (removed) size--;
return removed;
}
public int getSize() {
return size;
}
@Override
public String toString() {
return "MyHashSetV1{" +
"buckets=" + Arrays.toString(buckets) +
", size=" + size +
'}';
}
}
5. ๋ฌธ์์ด ํด์ ํจ์ ๊ตฌํ
โน๏ธ ๋ฌธ์ ์ : "BC"(66+67=133), "AD"(65+68=133) → ํด์ ์ถฉ๋ ๋ฐ์!
static int hashCode(String str) {
char[] chars = str.toCharArray();
int sum = 0;
for (char c : chars) {
sum += c; // ๊ฐ ๋ฌธ์์ ์ ๋์ฝ๋ ํฉ์ฐ
}
return sum;
}
static int hashIndex(int hashCode) {
return hashCode % 10; // capacity = 10 ๊ธฐ์ค
}
6. ์๋ฐ์ String ํด์์ฝ๋ ๊ณ์ฐ ๋ฐฉ์
- 31์ ๊ณฑํ๋ ์ด์ : ์ถฉ๋ ๋ฐฉ์ง + ๊ณ์ฐ ์ต์ ํ(31 = 32-1)
- equals()๊ฐ true์ธ ๊ฒฝ์ฐ์๋ ๋ฐ๋์ hashCode()๋ ๊ฐ์์ผ ํจ
String str = "AB";
int hash = 0;
for (char c : str.toCharArray()) {
hash = 31 * hash + c;
}
7. Object์ hashCode()๋ ์ฐธ์กฐ๊ฐ ๊ธฐ๋ฐ
โ๏ธ Object์ ๊ธฐ๋ณธ hashCode()๋ ์ฃผ์ ๊ธฐ๋ฐ์ด๋ฏ๋ก, ์๋ก ๋ค๋ฅธ ๊ฐ์ฒด๋ ๋ค๋ฅธ ๊ฐ
Object obj1 = new Object();
Object obj2 = new Object();
System.out.println(obj1.hashCode()); // ex) 123456
System.out.println(obj2.hashCode()); // ์๋ก ๋ค๋ฆ
8. Member ํด๋์ค ์์ (hashCode + equals ์ค๋ฒ๋ผ์ด๋ฉ)
public class Member {
private String id;
public Member(String id) {
this.id = id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Member)) return false;
Member other = (Member) o;
return Objects.equals(this.id, other.id); // id ๊ธฐ์ค ๋น๊ต
}
@Override
public int hashCode() {
return Objects.hash(id); // id์ ํด์์ฝ๋๋ฅผ ์ฌ์ฉ
}
@Override
public String toString() {
return "Member{id='" + id + "'}";
}
}
9. ์ง์ ๊ตฌํํ๋ Set - MyHashSetV2 (Object ํ์ ์ผ๋ก ํ์ฅ)
public class MyHashSetV2 {
static final int DEFAULT_INITIAL_CAPACITY = 16;
private LinkedList<Object>[] buckets;
private int size = 0;
private int capacity = DEFAULT_INITIAL_CAPACITY;
public MyHashSetV2(int capacity) {
this.capacity = capacity;
initBuckets();
}
private void initBuckets() {
buckets = new LinkedList[capacity];
for (int i = 0; i < capacity; i++) {
buckets[i] = new LinkedList<>();
}
}
private int hashIndex(Object value) {
return Math.abs(value.hashCode()) % capacity;
}
public boolean add(Object value) {
int hashIndex = hashIndex(value);
LinkedList<Object> bucket = buckets[hashIndex];
if (bucket.contains(value)) return false;
bucket.add(value);
size++;
return true;
}
public boolean contains(Object value) {
return buckets[hashIndex(value)].contains(value);
}
public boolean remove(Object value) {
boolean removed = buckets[hashIndex(value)].remove(value);
if (removed) size--;
return removed;
}
public int getSize() {
return size;
}
@Override
public String toString() {
return "MyHashSetV2{" +
"buckets=" + Arrays.toString(buckets) +
", size=" + size +
", capacity=" + capacity +
'}';
}
}
10. equals/hashCode ๋ฏธ๊ตฌํ ์ ๋ฐ์ ๋ฌธ์
โ๏ธ Object ๊ธฐ๋ณธ equals()๋ ์ฐธ์กฐ ๋น๊ต (==)
โ๏ธ hashCode()๋ง ์ค๋ฒ๋ผ์ด๋ฉํ๋ฉด equals() ์คํจ → ์ค๋ณต ๊ฐ์ง ๋ชป ํจ
โ๏ธ equals()๋ง ์ค๋ฒ๋ผ์ด๋ฉํด๋ ํด์ ๋ฒํท ์์น๊ฐ ๋ค๋ฅด๋ฉด ํ์ ๋ถ๊ฐ
โ๏ธ ๋ฐ๋์ ๋ ๋ค ๊ตฌํํด์ผ Set์์ ์ ์ ์๋
11. ์ ๋ค๋ฆญ ๊ธฐ๋ฐ์ Set ๊ตฌํ - MyHashSetV3
public class MyHashSetV3<E> implements MySet<E> {
static final int DEFAULT_INITIAL_CAPACITY = 16;
private LinkedList<E>[] buckets;
private int size = 0;
private int capacity = DEFAULT_INITIAL_CAPACITY;
public MyHashSetV3(int capacity) {
this.capacity = capacity;
initBuckets();
}
private void initBuckets() {
buckets = new LinkedList[capacity];
for (int i = 0; i < capacity; i++) {
buckets[i] = new LinkedList<>();
}
}
private int hashIndex(Object value) {
return Math.abs(value.hashCode()) % capacity;
}
@Override
public boolean add(E value) {
int hashIndex = hashIndex(value);
LinkedList<E> bucket = buckets[hashIndex];
if (bucket.contains(value)) return false;
bucket.add(value);
size++;
return true;
}
@Override
public boolean contains(E value) {
return buckets[hashIndex(value)].contains(value);
}
@Override
public boolean remove(E value) {
boolean removed = buckets[hashIndex(value)].remove(value);
if (removed) size--;
return removed;
}
public int getSize() {
return size;
}
@Override
public String toString() {
return "MyHashSetV3{" +
"buckets=" + Arrays.toString(buckets) +
", size=" + size +
", capacity=" + capacity +
'}';
}
}
12. ์ฉ์ด ์ ๋ฆฌ
| ์ฉ์ด | ์๋ฏธ |
| ํด์ ํจ์ | ๊ฐ์ฒด → ์ ์๊ฐ(ํด์ ์ฝ๋)์ผ๋ก ๋ฐ๊ฟ์ฃผ๋ ํจ์ |
| ํด์ ์ฝ๋ | ๊ฐ์ฒด๋ฅผ ๋ํํ๋ ์ ์๊ฐ |
| ํด์ ์ธ๋ฑ์ค | ํด์ ์ฝ๋ % ๋ฐฐ์ด ํฌ๊ธฐ |
| equals() | ๋ ๊ฐ์ฒด์ ๋ ผ๋ฆฌ์ ๋๋ฑ์ฑ ๋น๊ต |
| hashCode() | ๊ฐ์ฒด์ ํด์๊ฐ ๋ฐํ, equals์ ์ผ์นํด์ผ ํจ |
| Set ์๋ฃ๊ตฌ์กฐ | ์ค๋ณต ์์, ์์์์, equals/hashCode ๊ธฐ์ค ๋น๊ต |
<์ฐธ๊ณ > - ๊น์ํ์ ์ค์ ์๋ฐ ์ค๊ธ2ํธ ๊ฐ์ ์น์ 8. ์ปฌ๋ ์ ํ๋ ์์ํฌ ํด์(HashSet)
'Tech Stack > Java & Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [Spring] ์ค์ฒฉ ํด๋์ค์ DTO ์ค๊ณ (0) | 2025.09.03 |
|---|---|
| [์ปฌ๋ ์ ํ๋ ์์ํฌ] Set (0) | 2025.04.10 |
| [์ปฌ๋ ์ ํ๋ ์์ํฌ] ํด์(Hash) (0) | 2025.04.06 |
| [์ปฌ๋ ์ ํ๋ ์์ํฌ] List (0) | 2025.04.05 |
| [Java] ๋ฐฐ์ด ๋ด์ฉ ์ถ๋ ฅํ๋ ๋ฐฉ๋ฒ: Arrays.toString() (0) | 2024.10.17 |