Tech Stack/Java & Spring

[์ปฌ๋ ‰์…˜ ํ”„๋ ˆ์ž„์›Œํฌ] Set

_silver 2025. 4. 10. 21:20
1. Set์ด๋ž€?
  • ์ค‘๋ณต์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๊ณ , ์ˆœ์„œ๋ฅผ ๋ณด์žฅํ•˜์ง€ ์•Š๋Š” ์ž๋ฃŒ๊ตฌ์กฐ
  • ์ž๋ฐ”์—์„œ๋Š” Set ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ๊ตฌํ˜„์ฒด ์ œ๊ณต

2. ์ž๋ฐ”๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋Œ€ํ‘œ์ ์ธ Set ๊ตฌํ˜„์ฒด
๋”๋ณด๊ธฐ

โ˜‘๏ธŽ HashSet ์„ค๋ช…

ํŠน์ง• ์„ค๋ช…
๊ตฌํ˜„ ๋‚ด๋ถ€์ ์œผ๋กœ ํ•ด์‹œ ํ…Œ์ด๋ธ”์„ ์‚ฌ์šฉ
์ˆœ์„œ ๋ณด์žฅํ•˜์ง€ ์•Š์Œ(์ž…๋ ฅ ์ˆœ์„œ X)
์„ฑ๋Šฅ ํ‰๊ท  ์‹œ๊ฐ„ ๋ณต์žก๋„ O(1)
์šฉ๋„ ์ค‘๋ณต ์ œ๊ฑฐ๊ฐ€ ์ค‘์š”ํ•˜๊ณ  ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ

 

๋”๋ณด๊ธฐ

โ˜‘๏ธŽ LinkedHashSet ์„ค๋ช…

ํŠน์ง• ์„ค๋ช…
๊ตฌํ˜„ HashSet + ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ ๊ตฌ์กฐ
์ˆœ์„œ ์ž…๋ ฅ ์ˆœ์„œ๋ฅผ ์œ ์ง€
์„ฑ๋Šฅ HashSet๋ณด๋‹ค๋Š” ์•ฝ๊ฐ„ ๋А๋ฆฌ์ง€๋งŒ ์—ฌ์ „ํžˆ ๋น ๋ฆ„
์šฉ๋„ ์ž…๋ ฅ ์ˆœ์„œ๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ์ค‘๋ณต ์ œ๊ฑฐ๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์‚ฌ์šฉ
๋”๋ณด๊ธฐ

โ˜‘๏ธŽ TreeSet ์„ค๋ช…

ํŠน์ง• ์„ค๋ช…
๊ตฌํ˜„ ๋‚ด๋ถ€์ ์œผ๋กœ ๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ(์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ์˜ ์ผ์ข…) ์‚ฌ์šฉ
์ˆœ์„œ ์ž๋™ ์ •๋ ฌ๋จ (๊ธฐ๋ณธ์€ ์˜ค๋ฆ„์ฐจ์ˆœ, Comparator๋กœ ์ปค์Šคํ…€ ๊ฐ€๋Šฅ)
์„ฑ๋Šฅ O(log n) (์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ ๊ธฐ๋ฐ˜)
์šฉ๋„ ์ •๋ ฌ๋œ Set, ๋ฒ”์œ„ ๊ฒ€์ƒ‰์ด ํ•„์š”ํ•  ๋•Œ ์‚ฌ์šฉ

3. Set ์ข…๋ฅ˜๋ณ„ ๋น„๊ต ์˜ˆ์ œ
๋”๋ณด๊ธฐ
public class JavaSetMain {
    public static void main(String[] args) {
        run(new HashSet<>());          // ์ˆœ์„œ ๋ณด์žฅ X
        run(new LinkedHashSet<>());    // ์ž…๋ ฅ ์ˆœ์„œ ๋ณด์žฅ
        run(new TreeSet<>());          // ์ •๋ ฌ๋œ ์ˆœ์„œ ๋ณด์žฅ
    }

    private static void run(Set<String> set) {
        System.out.println("set = " + set.getClass());
        set.add("C");
        set.add("B");
        set.add("A");
        set.add("1");
        set.add("2");

        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        System.out.println();
    }
}

 

โ˜‘๏ธ ์‹คํ–‰ ๊ฒฐ๊ณผ

set = class java.util.HashSet
A 1 B 2 C

set = class java.util.LinkedHashSet
C B A 1 2

set = class java.util.TreeSet
1 2 A B C

4. TreeSet์˜ ๋‚ด๋ถ€ - ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ

โ˜‘๏ธŽ ์ด์ง„ ํƒ์ƒ‰ ํŠธ๋ฆฌ๋ž€?

  • ๋…ธ๋“œ์˜ ์™ผ์ชฝ์—๋Š” ๋” ์ž‘์€ ๊ฐ’, ์˜ค๋ฅธ์ชฝ์—๋Š” ๋” ํฐ ๊ฐ’์ด ๋“ค์–ด๊ฐ
  • ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฝ์ž…ํ•˜๋Š” ์ฆ‰์‹œ ์ •๋ ฌ๋œ ๊ตฌ์กฐ๋กœ ์œ ์ง€๋จ

โ˜‘๏ธŽ TreeSet์˜ ์žฅ์ 

  • ์ž๋™ ์ •๋ ฌ(Comparable ๋˜๋Š” Comparator ๊ธฐ๋ฐ˜)
  • ์ •๋ ฌ๋œ ๋ฒ”์œ„ ๊ฒ€์ƒ‰์ด ์‰ฌ์›€
  • ํƒ์ƒ‰/์‚ฝ์ž…/์‚ญ์ œ ์„ฑ๋Šฅ O(log n) ๋ณด์žฅ (๋ ˆ๋“œ-๋ธ”๋ž™ ํŠธ๋ฆฌ ๋•๋ถ„)

5. Set์˜ ์ค‘๋ณต ์ œ๊ฑฐ ์‹ค์ „ ์˜ˆ์ œ

โ˜‘๏ธŽ ๋ฌธ์ œ1 - ์ค‘๋ณต ์ œ๊ฑฐ(์ˆœ์„œ ์ƒ๊ด€ ์—†์Œ)

Integer[] arr = {30, 20, 20, 10, 10};
Set<Integer> set = new HashSet<>();

for (Integer n : arr) {
    set.add(n); // ์ค‘๋ณต ์ œ๊ฑฐ ์ž๋™ ์ฒ˜๋ฆฌ
}

for (Integer n : set) {
    System.out.println(n); // ์ˆœ์„œ ๋ณด์žฅ X
}

โ˜‘๏ธŽ ๋ฌธ์ œ2 - ์ค‘๋ณต ์ œ๊ฑฐ + ์ž…๋ ฅ ์ˆœ์„œ ์œ ์ง€

Integer[] arr = {30, 20, 20, 10, 10};
Set<Integer> set = new LinkedHashSet<>(List.of(arr));

for (Integer n : set) {
    System.out.println(n); // ์ž…๋ ฅ ์ˆœ์„œ๋Œ€๋กœ ์ถœ๋ ฅ: 30, 20, 10
}

โ˜‘๏ธŽ ๋ฌธ์ œ3 - ์ค‘๋ณต ์ œ๊ฑฐ + ์ •๋ ฌ๋œ ์ˆœ์„œ ์ถœ๋ ฅ

Set<Integer> set = new TreeSet<>(List.of(30, 20, 20, 10, 10));

for (Integer n : set) {
    System.out.println(n); // ์ •๋ ฌ๋œ ์ˆœ์„œ: 10, 20, 30
}

6. Set ์—ฐ์‚ฐ(ํ•ฉ์ง‘ํ•ฉ, ๊ต์ง‘ํ•ฉ, ์ฐจ์ง‘ํ•ฉ)
Set<Integer> set1 = new HashSet<>(List.of(1, 2, 3, 4, 5));
Set<Integer> set2 = new HashSet<>(List.of(3, 4, 5, 6, 7));

// ํ•ฉ์ง‘ํ•ฉ
Set<Integer> union = new HashSet<>(set1);
union.addAll(set2); // ๋ชจ๋“  ์š”์†Œ ํ•ฉ์น˜๊ธฐ

// ๊ต์ง‘ํ•ฉ
Set<Integer> intersection = new HashSet<>(set1);
intersection.retainAll(set2); // ๊ณตํ†ต ์š”์†Œ๋งŒ ๋‚จ๊ธฐ๊ธฐ

// ์ฐจ์ง‘ํ•ฉ
Set<Integer> difference = new HashSet<>(set1);
difference.removeAll(set2); // set2 ์š”์†Œ ์ œ๊ฑฐ

System.out.println("ํ•ฉ์ง‘ํ•ฉ: " + union);
System.out.println("๊ต์ง‘ํ•ฉ: " + intersection);
System.out.println("์ฐจ์ง‘ํ•ฉ: " + difference);

 


7. equals & hashCode ์˜ค๋ฒ„๋ผ์ด๋”ฉ ์˜ˆ์ œ
public class Rectangle {
    private int width;
    private int height;

    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Rectangle)) return false;
        Rectangle r = (Rectangle) o;
        return width == r.width && height == r.height;
    }

    @Override
    public int hashCode() {
        return Objects.hash(width, height); // width + height ๊ธฐ์ค€ ํ•ด์‹œ ์ƒ์„ฑ
    }

    @Override
    public String toString() {
        return "Rectangle{" + "width=" + width + ", height=" + height + '}';
    }
}
Set<Rectangle> set = new HashSet<>();
set.add(new Rectangle(10, 10));
set.add(new Rectangle(20, 20));
set.add(new Rectangle(20, 20)); // ์ค‘๋ณต์œผ๋กœ ์ €์žฅ ์•ˆ ๋จ

for (Rectangle r : set) {
    System.out.println("rectangle = " + r);
}

8. HashSet์˜ ์„ฑ๋Šฅ ์ตœ์ ํ™” ์›๋ฆฌ
  • ๊ธฐ๋ณธ ๋ฒ„ํ‚ท ํฌ๊ธฐ: 16
  • ๋ถ€ํ•˜์œจ(load factor): 0.75 (75%)
  • ๋ฒ„ํ‚ท ์‚ฌ์šฉ๋ฅ ์ด 75%๋ฅผ ๋„˜์œผ๋ฉด → ๋ฐฐ์—ด ํฌ๊ธฐ๋ฅผ 2๋ฐฐ๋กœ ํ™•์žฅ + ๋ชจ๋“  ์š”์†Œ ์žฌ๋ฐฐ์น˜(rehashing)
  • ์„ฑ๋Šฅ ์œ ์ง€๋ฅผ ์œ„ํ•ด ํ•„์š”ํ•œ ๋น„์šฉ์ด์ง€๋งŒ, ์ž๋ฐ”๊ฐ€ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌ

9. ์ •๋ฆฌ
  • HashSet  : ์ค‘๋ณต ์ œ๊ฑฐ
  • LinkedHashSet : ์ค‘๋ณต ์ œ๊ฑฐ + ์ˆœ์„œ ์œ ์ง€
  • TreeSet : ์ค‘๋ณต์ œ๊ฑฐ + ์ •๋ ฌ ์œ ์ง€
๊ตฌํ˜„์ฒด ์ค‘๋ณต ์ œ๊ฑฐ ์ˆœ์„œ ๋ณด์žฅ ์ž๋™ ์ •๋ ฌ ์ˆœ์„œ
HashSet O X X ๋งค์šฐ ๋น ๋ฆ„ O(1)
LinkedHashSet O O (์ž…๋ ฅ ์ˆœ์„œ) X ๋ณดํ†ต
TreeSet O O (๊ฐ’ ์ •๋ ฌ ์ˆœ์„œ) O ๋А๋ฆผ O(log n)

 

<์ฐธ๊ณ > - ๊น€์˜ํ•œ์˜ ์‹ค์ „ ์ž๋ฐ” ์ค‘๊ธ‰2ํŽธ ๊ฐ•์˜ ์„น์…˜ 9. ์ปฌ๋ ‰์…˜ ํ”„๋ ˆ์ž„์›Œํฌ Set