🧩 Programming Languages/Java Grammar

5. 집합, 상수 집합 enum, 매직 넘버란?

복숭아아이스티에샷추가 2024. 5. 14. 14:00

 

 집합(Set) 자료형 

: 집합과 관련된 것을 쉽게 처리하기 위해 만든 것

 

종류는 HashSet, TreeSet, LinkedHashSet 등이 있는데  주로 HashSet 을 사용 


 

1. 특징

 

(1)  중복 허용 안 됨 

-> 자료형의 중복을 제거하기 위한 필터 역할로 종종 사용

 

(2)  순서가 없음 

-> 인덱싱 불가

 

 

그런데 집합에 입력한 순서대로 데이터를 가져오거나 오름차순으로 정렬된 데이터를 가져오고 싶다면 TreeSet 혹은 LinkedHashSet 을 사용하면 된다.

 

- TreeSet : 값을 오름차순으로 정렬해 저장

- LinkedHashSet : 값을 입력한 순서대로 정렬

 


 

2. 쓰임

 

아래와 같이 집합 자료형 2개가 있다고 가정한다. 이 두 집합의 교집합, 합집합, 차집합을 구할 수 있다.

import java.util.Arrays;
import java.util.HashSet;

public class Sample {
    public static void main(String[] args) {
        HashSet<Integer> s1 = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5, 6));
        HashSet<Integer> s2 = new HashSet<>(Arrays.asList(4, 5, 6, 7, 8, 9));
    }
}

 

 

 

(1)  retainAll  : 교집합

HashSet<Integer> intersection = new HashSet<>(s1);  // s1으로 intersection 생성
intersection.retainAll(s2);  // 교집합 수행
System.out.println(intersection);  // [4, 5, 6] 출력

 

(2)  addAll  : 합집합

HashSet<Integer> union = new HashSet<>(s1);  // s1으로 union 생성
union.addAll(s2); // 합집합 수행
System.out.println(union);  // [1, 2, 3, 4, 5, 6, 7, 8, 9] 출력

 

(3) removeAll  : 집합

HashSet<Integer> substract = new HashSet<>(s1);  // s1으로 substract 생성
substract.removeAll(s2); // 차집합 수행
System.out.println(substract);  // [1, 2, 3] 출력

 

 

(4)  add  : 집합 자료형에 값을 추가

import java.util.HashSet;

public class Sample {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        set.add("Jump");
        set.add("To");
        set.add("Java");
        System.out.println(set);  // [Java, To, Jump] 출력
    }
}

 

(5)  addAll  : 여러 값 한번에 추가

set.addAll(Arrays.asList("Go", "Go", "Ssing"));
System.out.println(set);  // [Java, To, Jump, GO, Go, Ssing ] 출력

 

(6)  remove  : 값 삭제

set.remove("Ssing");
System.out.println(set);  // [Java, To, Jump, GO, Go ] 출력

 


 

 

 enum 자료형 

: 서로 연관 있는 여러 개의 상수 집합을 정의할 때 사용

 

장점 1. 매직 넘버를 사용할 때보다 코드가 명확하다.

더보기

매직넘버란? : 하드 코딩된 일정한 값

 

가독성 저하, 유지보수가 어려움, 예상치 못한 버그를 발생시키는 원인이 될 수 있기 때문에

상수나 변수를 사용하는 것이 좋다.

 

예시

// 매직넘버 3.14 사용
function calculateArea(radius) {
  return 3.14 * radius * radius;
}
// PI 라는 상수를 정의
const PI = 3.14;

function calculateArea(radius) {
  return PI * radius * radius;
}

장점 2. 잘못된 값을 사용해 생길 수 있는 오류를 막을 수 있다.

 

 

예제

public class Sample {
    
    enum CoffeeType {
        AMERICANO,
        ICE_AMERICANO,
        CAFE_LATTE
    };

    public static void main(String[] args) {
        System.out.println(CoffeeType.AMERICANO);  // AMERICANO 출력
        System.out.println(CoffeeType.ICE_AMERICANO);  // ICE_AMERICANO 출력
        System.out.println(CoffeeType.CAFE_LATTE);  // CAFE_LATTE 출력
    };
    
    public static void main(String[] args) {
        for(CoffeeType type: CoffeeType.values()) {
            System.out.println(type);  // 순서대로 AMERICANO, ICE_AMERICANO, CAFE_LATTE 출력
        }
    };
}

 

 

만약 아래와 같은 메서드도 추가될 때 아메리카노의 판매 개수를 알려면,

// 판매된 커피의 갯수를 리턴하는 메서드 
// 커피의 종류 (1: 아메리카노, 2: 아이스 아메리카노, 3: 카페라떼)
// 종류별로 판매된 커피의 개수를 리턴
int countSellCoffee(int type) {
    ... 생략 ...
}

 

다음과 같이 숫자 1을 넘겨야 한다.

하지만 이 방식은 숫자 1이 아메리카노라고 기억하며 사용해야 해서 불편하다.

int americano = countSellCoffee(1);

 

또한 다음과 같이 사용할 때에도 문제가 발생

int result = countSellCoffee(99);  // 99라는 커피의 종류는 존재하지 않으므로 오류가 발생한다.

 

 

따라서 아래와 같이 바꿔준다면

int countSellCoffee(CoffeType type) {
    ... 생략 ...
}

 

메서드를 호출할 때 숫자 대신 CoffeeType을 인수로 사용하면 된다.

int americano = countSellCoffee(CoffeType.AMERICANO);  // 아메리카노의 판매갯수