개발자로 후회없는 삶 살기
[문법] 객체 상수를 편리하게 다룰 수 있는 Enum 타입 본문
서론
※ 과거에 기록한 내용에서 중요한 부분만 발췌하여 모두가 이해하기 쉽게 다시 서술한다.
본론
- 열거형
public enum WeekType {
MONDAY,
TUESDAY
}
열거형은 한정된 값을 가지는 상수들의 집합이다. 열거형을 사용하면 상수값을 편하게 사용할 수 있다.
public class WeekType {
public static final WeekType MONDAY = new WeekType();
}
enum은 위 코드와 사실상 같다. 클래스 내부에 열거형 객체를 상수로 가지고 있는 것이다.
- name과 필드
public enum WeekType {
MONDAY("월요일"),
TUESDAY("화요일");
String desc;
private WeekType(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
}
열거형은 사실상 클래스로 상수를 편리하게 사용하기 위한 Enum만의 문법을 가지고 있다. 클래스이기에 생성자와 변수, 메서드를 가질 수 있다. 생성자는 private 접근 지정자를 사용하여 Enum 타입의 인스턴스를 만들어서 다른 용도로 사용하는 것을 방지하고 있다.
public enum WeekType {
MONDAY("월요일", List.of("축구","치킨")),
TUESDAY("화요일", List.of("노래방","야구"));
String desc;
List<String> playList;
WeekType(String desc, List<String> playList) {
this.desc = desc;
this.playList = playList;
}
public String getDesc() {
return desc;
}
}
변수는 여러 개 추가할 수 있고 생성자에 타입만 맞춰주면 다양하게 사용할 수 있다.
public static WeekType from(WeekType weekType) {
return Arrays.stream(values())
.filter(weekType1 -> weekType1 == weekType)
.findFirst()
.orElseThrow();
}
Enum은 기본이 싱글톤이라서 변수에 static을 붙이지 않고 공유하여 사용되며, 동일 메모리를 가지기에 == 비교가 가능하고, type safe 하다.
public enum WeekType {
MONDAY("월요일", List.of("축구","치킨"), (name, order) -> name.equals("월요일") && order.equals("첫번째")),
TUESDAY("화요일", List.of("노래방","야구"), (name, order) -> name.equals("화요일") && order.equals("두번째"));
String desc;
List<String> playList;
private final BiPredicate<String, String> expression;
WeekType(String desc, List<String> playList, BiPredicate<String, String> expression) {
this.desc = desc;
this.playList = playList;
this.expression = expression;
}
public String getDesc() {
return desc;
}
public static WeekType of(final String name, final String order) {
return Arrays.stream(values())
.filter(value -> value.expression.test(name, order))
.findFirst()
.orElseThrow();
}
}
함수형 인터페이스를 변수로 넣어 조건에 맞는 Enum 객체를 찾을 수도 있다.
Enum은 Stream으로 편리하게 원하는 Enum 객체를 찾을 수 있어서 검색 조건을 Predicate 함수형 인터페이스로 만들면 다차원으로 검색 조건을 지정할 수 있다.
- 메서드
열거형 객체는 상수 집합에 접근하기 위한 메서드를 가지고 있다.
for (WeekType value : WeekType.values()) {
log.info("values() = {}", value);
}
log.info("name() = {}", WeekType.MONDAY.name());
log.info("desc() = {}", WeekType.MONDAY.desc);
log.info("valueOf() = {}", WeekType.valueOf("MONDAY"));
values()로 상수 집합을 순회하고 valueOf로 이름에 맞는 상수 객체를 반환할 수 있다.
🚨 EnumMap을 사용하자
Map 인터페이스에서 키를 특정 enum 타입만을 사용하도록 하는 구현체이다.
Map.Entry(MONDAY : 1)
Map.Entry(TUESDAY : 2)
위 ENUM을 Map 형식으로 저장할 수 있으며 키로는 특정 Enum 객체만 가능하다.
monday = 1 번 인덱스
tuesday = 2 번 인덱스
enum은 ordinal이라는 정의한 순서대로 순차적인 정수값을 가지고 있다.
EnumMap은 내부에 데이터를 Array에 저장하며, 순차적이기 때문에 HashMap처럼 해시를 만들고 HashCollision에 대응하는 작업 자체가 필요없어진다. 따라서 다른 Map에 비해 성능면에서 우수하고 enum 타입만을 키로 받기 때문에 명확하게 자료구조를 사용할 수 있다.
-> 사용법 예제
Collections의 checked처럼 한 종류의 enum 타입만 저장하기 위해 타입을 인자로 준다.
EnumMap<WeekType, Integer> map = new EnumMap<>(WeekType.class);
벨류는 원하는 타입을 주면 된다.
null을 키로 넣는 것도 방지하고 있다.
월요일, 화요일의 개수를 enum으로 저장하고 있을 때 사용할 수 있겠다.
'[백엔드] > [Java | 학습기록]' 카테고리의 다른 글
[문법] Comparator, Comparable 정렬 원리 (0) | 2024.05.27 |
---|---|
[문법] 인터페이스의 익명 객체 람다 (0) | 2024.05.25 |
[문법] 스프링 코드 분석을 위해서 반드시 알아야 하는 인터페이스 (0) | 2024.05.19 |
[문법] 상속은 코드의 재활용이 아니다. (0) | 2024.05.18 |
[문법] 접근 지정자와 static 동작 원리 (0) | 2024.05.17 |