코딩하는 털보

STUDY HALLE - 11주차 본문

Diary/Study Halle

STUDY HALLE - 11주차

이정인 2021. 1. 29. 22:09

STUDY HALLE

11주차 : Enum


목표

자바의 열거형에 대해 학습하세요.

학습할 것

  • enum 정의하는 방법
  • enum이 제공하는 메소드
  • java.lang.Enum
  • EnumSet / EnumMap

Enum Type

enum type은 특수한 데이터 타입으로, 미리 정의된 상수(enum constant)의 모음이다.

과거에는 int Enum 패턴을 통해 열거형을 나타내었으나,

//과거의 enum 표현법
public static final int DAY_SUNDAY = 0;
public static final int DAY_MONDAY = 1;
public static final int DAY_TUESDAY = 2;
public static final int DAY_WEDNESDAY = 3;
public static final int DAY_THURSDAY = 4;
public static final int DAY_FRIDAY = 5;
public static final int DAY_SATURDAY = 6;

아래 문제를 해결하지 못하였다.

  • Not typesafe

    enum 이 정수형(int) 타입을 가지게 되어 연산가능하고 다른 숫자 변수에 대입되는 타입 불안정.

  • No namespace

    다른 enum type과 구분하기 위한 네임스페이스가 없어서 prefix를 사용한다.

  • Brittleness

    기존 상수 두 개 사이에 새 상수가 추가되거나 순서가 변경되면 클라이언트를 다시 컴파일해야한다. 그렇지 않은 경우 동작이 재정립되지 않는다.

  • Printed values are uninformative

    정수형 이므로 출력 결과에 아무런 의미가 없다.

참고 : https://docs.oracle.com/javase/8/docs/technotes/guides/language/enums.html

Java 1.5 부터 문법적으로 enum type을 사용할 수 있도록 제공된다.

public enum Day {
    //enum constant
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY 
}

모든 enum type은 java.lang.Enum 클래스를 상속받기 때문에 Enum 클래스에서 구현된 메소드를 사용할 수 있으며 추가적으로 다른 클래스를 상속받을 수 없다.

바이트코드를 확인해보면 모든 enum 상수는 public static final 키워드로 만들어지는 enum 객체와 같다.

> javap -c Day
Compiled from "Day.java"
public final class me.rockintuna.demospringdata.Day extends java.lang.Enum<me.rockintuna.demospringdata.Day> {
  public static final me.rockintuna.demospringdata.Day SUNDAY;

  public static final me.rockintuna.demospringdata.Day MONDAY;

  public static final me.rockintuna.demospringdata.Day TUESDAY;

  public static final me.rockintuna.demospringdata.Day WEDNESDAY;

  public static final me.rockintuna.demospringdata.Day THURSDAY;

  public static final me.rockintuna.demospringdata.Day FRIDAY;

  public static final me.rockintuna.demospringdata.Day SATURDAY;

  ~
}

그 외에 values()나 valueOf() 등 자동으로 생성되는 메소드들도 확인할 수 있다.

  public static me.rockintuna.demospringdata.Day[] values();
    Code:
       0: getstatic     #1                  // Field $VALUES:[Lme/rockintuna/demospringdata/Day;
       3: invokevirtual #2                  // Method "[Lme/rockintuna/demospringdata/Day;".clone:()Ljava/lang/Object;
       6: checkcast     #3                  // class "[Lme/rockintuna/demospringdata/Day;"
       9: areturn

  public static me.rockintuna.demospringdata.Day valueOf(java.lang.String);
    Code:
       0: ldc           #4                  // class me/rockintuna/demospringdata/Day
       2: aload_0
       3: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
       6: checkcast     #4                  // class me/rockintuna/demospringdata/Day
       9: areturn

enum의 또다른 특징은 생성자를 사용할 수 있으나, private 또는 default(package-private) 이어야 한다는 것이다.

//생성할 수 는 있지만..
Day() {
        System.out.println(this.name());
}
class DayTest {

    @Test
    public void test() {
        //사용하면 컴파일 에러 발생?
        Day day = new Day();
    }
}

enum의 생성자는 직접 호출할 수 없고 enum 상수를 가져오려면 다른 방법을 사용해야 한다.

enum 상수 가져오기

//Day enum type 상수 가져오기
Day day1 = Day.FRIDAY;
Day day2 = Day.valueOf("FRIDAY");

참고 : https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html


enum 정의하기

enum의 선언은 새로운 클래스를 정의하는 것과 같으며, 이때 정의되는 클래스를 enum type class 라고 한다.

열거 형 클래스에는 미리 정의하는 enum 상수 외에도 일반적인 클래스 처럼 메소드나 필드를 추가할 수 있다. 특히, 컴파일러는 열거 형 클래스에 몇가지 특수한 메소드(values(), valueOf(), ...)를 자동으로 추가한다.

참고 : https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

enum 정의하기

class 대신 enum 키워드를 사용하면 열거 형 클래스를 생성할 수 있다.

enum 상수는 대문자로 작성한다는 특징이 있다.

enum 상수는 enum 본문의 최상단에 위치해야 하며, 만약 상수 외에 다른 메소드나 필드가 있다면 마지막 상수 값 뒤에 콜론을 추가해야한다.

package me.rockintuna.demospringdata;

public enum Day {
    //enum constant
        //상징적으로 상수라고 알리기 위해 대문자로 입력한다.
        //메소드가 있으므로 마지막에 콜론으로 끝낸다.
    //선언에서 생성자에 대한 파라미터를 입력할 수 있다.
    SUNDAY(5), MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(10), SATURDAY(9);

    //필드를 만들 수 있다.
    public int score;

    //생성자를 만들 수 있다.
    Day(int score) {
        this.score = score;
    }

    //메소드를 만들 수 있다.
    public void tellItLikeItIs() {
        switch (this.name()) {
            case "MONDAY":
                System.out.println("Mondays are bad.");
                break;

            case "FRIDAY":
                System.out.println("Fridays are better.");
                break;

            case "SATURDAY":
            case "SUNDAY":
                System.out.println("Weekends are best.");
                break;

            default:
                System.out.println("Midweek days are so-so.");
                break;
        }
    }
}

enum 사용하기

class DayTest {

    @Test
    public void test() {}
        //enum 객체 생성하기.
        Day day = Day.FRIDAY;
        //내가 만든 메소드 사용가능.
        day.tellItLikeItIs();
        //컴파일러가 자동으로 생성해준 name() 메소드 사용가능.
        System.out.println(day.name());        
    }
} 

enum이 제공하는 메소드

enum을 정의했을 때 Enum 클래스로부터 상속받는 메소드는 어떤 것이 있는지 알아보자.

  • String name()

    enum에 선언된 정확한 상수 이름를 반환한다.

  • String toString()

    enum 선언에 포함된 상수 이름를 반환한다.

enum의 name() 메소드와 toString() 메소드의 차이점?

Enum 클래스에서는 두 메소드 모두 enum에서 정의된 상수의 이름를 반환하도록 구현되어 있다.

    public final String name() {
        return name;
    }

    public String toString() {
        return name;
    }

차이는 보이는 것 처럼 name() 메소드는 final 메소드이고 toString()은 그렇지 않은데에 있다. 즉, toString()은 개발자가 언제든지 재정의하여 사용할 수 있지만 name()은 그렇지 않다는 것이다.

Java Docs에는 이 차이를 아래와 같이 설명한다.

"대부분의 프로그래머는 name() 을 직접 사용하는 것 보다 toString() 메서드를 재정의하여 더 친숙한 상수의 이름을 반환하게 할 수 있으므로 우선적으로 toString() 메서드를 사용해야합니다. name() 메소드는 주로 정확한 이름을 얻는 데 의존하는 특수한 상황에서 사용하도록 설계되었으며 이는 릴리스마다 다르지 않습니다."
https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html

설명대로 우리는 enum 상수 이름을 확인하기 위해서 toString()을 사용하되, 만약 enum 상수 이름이 특정 값과 일치하는 지 확인하는 로직 등, 정확한 값을 반환해야 할 때는 name()을 사용하면 되겠다.

  • T valueOf(String name)

    지정된 이름(name 파라미터)을 가진 enum 상수를 반환한다. 이름은 선언된 enum 상수 중에서 하나와 정확히 일치해야한다. 반환된 상수는 enum type과 동일한 타입이다.

    만약 일치하지 않는 값을 주면 IllegalArgumentException 런타임 예외가 발생한다.

class DayTest {

    @Test
    public void test() {
        //띄어쓰기도 허용하지 않는다.
        System.out.println(Day.valueOf("FRI DAY"));
        }
}
java.lang.IllegalArgumentException: No enum constant me.rockintuna.demospringdata.Day.FRI DAY
  • valueOf(Class<T> enumType, String name)

    지정된 특정 enum type T 로부터 지정된 이름(name 파라미터)을 가진 지정된 enum 을 반환한다. 이름은 이 유형에서 열거 형 상수를 선언하는 데 사용되는 식별자와 정확히 일치해야한다.

    T valueOf(String name)의 경우, 이 메소드의 enumType 파라미터에 메소드를 호출하는 enum 객체의 클래스가 자동으로 주입되는 것이다.

class DayTest {

    @Test
    public void test() {
        //두 출력의 결과는 같다.
        System.out.println(Day.valueOf("FRIDAY"));
        System.out.println(Enum.valueOf(Day.class,"FRIDAY"));
    }

}
  • T[] values()

    enum 타입의 모든 enum 상수를 enum의 타입 배열로 반환한다.

        for (Day value : Day.values()) {
            System.out.println(value.toString());
        }
SUNDAY
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY

모든 enum 상수를 가져오는 다른 방법

java.lang.Class 클래스의 getEnumConstants() 메소드를 사용하면 해당 열거형 클래스의 모든 enum 상수를 객체 배열로 가져올 수 있다.

class DayTest {

    @Test
    public void test() {
        Class enumClass = Day.class;
        Object[] enumConstants = enumClass.getEnumConstants();
        System.out.println(Arrays.toString(enumConstants));
    }
}
  • int ordinal()

    해당 enum 상수가 enum 정의에서 정의된 순서(0부터 시작)를 반환한다.

class DayTest {

    @Test
    public void test() {
        Day day = Day.FRIDAY;
        assertThat(day.ordinal()).isEqualTo(5);
    }
}

ordinal() 메소드는 enum 상수를 구분하는 프로그램 코드에서 사용되지 않는 편인데, 그 이유는 enum 상수의 추가, 제거, 변경에 예민하기 때문이다.

public enum Day {
    //새로운 상수 추가
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;

    //순서 반환 메소드
    public int order() {
        return ordinal()+1;
    }

}
class DayTest {

    @Test
    public void test() {
        Day day = Day.FRIDAY;
        assertThat(day.order()).isEqualTo(6); 
    }
}

이러한 코드는 enum 상수의 순서 변경에 따라 예상치 못한 프로그램 문제를 발생시킬 수 있고 불가피하게 변경된 enum 상수의 순서로 인해 코드의 모든 수치가 변경되어야 하기 때문에 유지보수가 어렵게 된다.

Java Docs에는 ordinal() 메소드에 대해 주의하고 있다.

대부분 프로그래머는 이 메서드를 쓸 일이 없습니다.
이 메서드는 EnumSet과 EnumMap 같은 열거 타입 기반의 범용 자료구조에 쓸 목적으로 설계되었습니다.

https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html


Enum Class

java.lang.Enum

모든 java 열거형 클래스의 상위 추상클래스이다.

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {

    //enum 상수의 이름을 저장할 필드
    private final String name;

    public final String name() {
        return name;
    }

    //enum 상수의 순서를 저장할 필드
    private final int ordinal;

    public final int ordinal() {
        return ordinal;
    }

    //상속받은 클래스에서 사용될수 있도록 protected로 생성자가 있다.
    //상수 불러오기에 이 생성자가 자동으로 사용된다.
    protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }

    ~

    public static <T extends Enum<T>> T valueOf(Class<T> enumType,
                                                String name) {
        T result = enumType.enumConstantDirectory().get(name);
        if (result != null)
            return result;
        if (name == null)
            throw new NullPointerException("Name is null");
        throw new IllegalArgumentException(
            "No enum constant " + enumType.getCanonicalName() + "." + name);
    }

    ~

}

추상클래스이지만 추상메소드는 없으므로 추가적으로 구현해야하는건 없다.

다만, 이 클래스에서는 values() 메소드가 구현되지 않았는데 그래도 사용할 수 있는 이유는 의문이다.

참고 : https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html

Enum 클래스는 특별히 Comparable 인터페이스와 Serializable 인터페이스를 구현하였다.

Comparable

Comparable 인터페이스는 구현한 클래스의 객체 순서를 정의하기 위한 인터페이스이다.

Comparable 인터페이스의 int compareTo(T o) 메소드를 구현하여 사용한다.

구현할 때는 아래의 규칙을 생각하며 구현해야한다.

  • e1.compareTo(e2) == 0 : 순서가 동일하다.
  • e1.compareTo(e2) > 0 : e1 이 e2 보다 더 크다.
  • e1.compareTo(e2) < 0 : e1 이 e2 보다 더 작다.

이를 통해 인원의 ID를 통해 순서를 정하는 클래스를 구현할 수 있다.

public class Member implements Comparable<Member> {

    public int memberId;
    public String name;

    public Member(int memberId, String name) {
        this.memberId = memberId;
        this.name = name;
    }

    @Override
    public int compareTo(Member member) {
        return this.memberId - member.memberId;
    }
}

이렇게 순서를 정의하면 Collection 내 요소의 순서로 사용할 수 있다.

class MemberTest {

    @Test
    public void test() {
        Member member3 = new Member(3, "djkim");
        Member member2 = new Member(2, "cyrock");
        Member member1 = new Member(1, "jilee");

        List<Member> members = new ArrayList<>();
        members.add(member3);
        members.add(member2);
        members.add(member1);

        //321
        for (Member member : members) {
            System.out.println(member.name);
        }

        System.out.println("=============");

        //Collection 정렬하기
        Collections.sort(members);

        //123
        for (Member member : members) {
            System.out.println(member.name);
        }
    }
}

Comparable 인터페이스를 구현한 클래스는 Map의 key로 사용되거나 SortedSet의 요소로 사용될 수 도 있다.

Comparable 인터페이스 대신 정렬에 사용할 Comparator를 직접 구현할 수 도 있다.

public class MemberComparator implements Comparator<Member> {
    @Override
    public int compare(Member o1, Member o2) {
        return o1.memberId - o2.memberId;
    }
}
class MemberTest {

    @Test
    public void test() {
        Member member3 = new Member(3, "djkim");
        Member member2 = new Member(2, "cyrock");
        Member member1 = new Member(1, "jilee");

        List<Member> members = new ArrayList<>();
        members.add(member3);
        members.add(member2);
        members.add(member1);
        for (Member member : members) {
            System.out.println(member.name);
        }

        System.out.println("=============");

        //Comparator를 파라미터로 사용한다.
        Collections.sort(members, new MemberComparator());

        for (Member member : members) {
            System.out.println(member.name);
        }
    }
}

참고 : https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html

Serializable

Serializable 인터페이스를 구현하는 클래스는 직렬화가 활성화 된다.

Serializable 인터페이스에는 메서드나 필드가 없으며 단순히 직렬화 가능의 의미를 식별하는 역할만 한다.

직렬화?

객체가 직렬화가능하다는 것은 해당 상태를 바이트 스트림으로 변환(직렬화)하고 바이트 스트림을 객체의 복사본으로 되돌릴(역 직렬화) 수 있음을 의미한다.

보통 JVM의 메모리에서만 상주되어있는 객체 데이터를 그대로 영속화(Persistence)가 필요할 때 사용된다.

자세한 내용은 13주차 I/O에서 다루기로 하고 패스~

참고 : https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html

,https://docs.oracle.com/javase/tutorial/jndi/objects/serial.html

,https://woowabros.github.io/experience/2017/10/17/java-serialize.html


EnumSet / EnumMap

Class EnumSet

enum과 함께 사용하기위한 특수한 Set 구현체이다.

  • EnumSet의 모든 요소는 EnumSet을 만들 때 지정된 enum type에서 가져와야한다.
  • Null을 허용하지 않는다. (Null 삽입 요청 시 NullPointerException)
  • 멀티쓰레드 프로그래밍에서 동기화 되지 않는다. (외부 동기화 필요)

메소드 살펴보기

  • EnumSet<E> allOf<E>(Class<E> elementType)

    지정된 enum type class의 모든 요소를 포함하는 EnumSet을 반환한다.

    class DayTest {
    
        @Test
        public void test() {
            EnumSet<Day> dayEnumSet = EnumSet.allOf(Day.class);
    
            //java.util.RegularEnumSet
            System.out.println(dayEnumSet.getClass());
    
            //AbstractCollection 추상클래스에서 재정의 되어있는 toString() 사용.
            System.out.println(dayEnumSet); 
    
            for (Day day : dayEnumSet) {
                System.out.println(day.name());
            }
        }
    }
    class java.util.RegularEnumSet
    [SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY]
    SUNDAY
    MONDAY
    TUESDAY
    WEDNESDAY
    THURSDAY
    FRIDAY
    SATURDAY
  • EnumSet<E> complementOf(EnumSet<E> s)

    지정된 EnumSet과 동일한 타입의 비어있는 EnumSet을 반환한다.

    class DayTest {
    
        @Test
        public void test() {
            EnumSet<Day> source = EnumSet.allOf(Day.class);
            EnumSet<Day> dayEnumSet = EnumSet.complementOf(source);
            System.out.println(dayEnumSet.getClass());
            System.out.println(dayEnumSet);
            for (Day day : dayEnumSet) {
                System.out.println(day.name());
            }
        }
    }
    class java.util.RegularEnumSet
    [] ##비어있음!
  • EnumSet<E> copyOf(Collection<E> c)

    지정된 Collection에서 초기화 된 EnumSet을 반환한다. 새 EnumSet의 enum type을 결정하기 위해 지정된 Collection에는 하나 이상의 요소가 포함되어있어야한다. (비어있는 Collection인 경우 IllegalArgumentException 예외 발생)

    class DayTest {
    
        @Test
        public void test() {
            List<Day> days = new ArrayList<>();
            days.add(Day.MONDAY);
            days.add(Day.TUESDAY);
            days.add(Day.FRIDAY);
            EnumSet<Day> dayEnumSet = EnumSet.copyOf(days);
            System.out.println(dayEnumSet.getClass());
            System.out.println(dayEnumSet);
            for (Day day : dayEnumSet) {
                System.out.println(day.name());
            }
        }
    }
    class java.util.RegularEnumSet
    [MONDAY, TUESDAY, FRIDAY]
    MONDAY
    TUESDAY
    FRIDAY
  • EnumSet<E> copyOf(EnumSet<E> s)

    지정된 EnumSet과 동일한 enum type을 사용하여 동일한 요소(있는 경우)를 포함하는 EnumSet을 반환한다.

    class DayTest {
    
        @Test
        public void test() {
            EnumSet<Day> source = EnumSet.allOf(Day.class);
            EnumSet<Day> dayEnumSet = EnumSet.copyOf(source);
            System.out.println(dayEnumSet.getClass());
            System.out.println(dayEnumSet);
            for (Day day : dayEnumSet) {
                System.out.println(day.name());
            }
        }
    }
    class java.util.RegularEnumSet
    [SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY]
    SUNDAY
    MONDAY
    TUESDAY
    WEDNESDAY
    THURSDAY
    FRIDAY
    SATURDAY
  • EnumSet<E> noneOf(Class<E> elementType)

    지정된 enum type class를 사용하여 비어있는 EnumSet을 반환한다.

    class DayTest {
    
        @Test
        public void test() {
            EnumSet<Day> dayEnumSet = EnumSet.noneOf(Day.class);
            System.out.println(dayEnumSet.getClass());
            System.out.println(dayEnumSet);
            for (Day day : dayEnumSet) {
                System.out.println(day.name());
            }
        }
    }
    class java.util.RegularEnumSet
    []
  • EnumSet<E> of(E e) , EnumSet<E> of(E e1, E e2 ...)

    지정된 enum 상수를 포함하는 EnumSet을 반환한다.

    class DayTest {
    
        @Test
        public void test() {
    
            EnumSet<Day> dayEnumSet = EnumSet.of(Day.FRIDAY, Day.MONDAY);
            System.out.println(dayEnumSet.getClass());
            System.out.println(dayEnumSet);
            for (Day day : dayEnumSet) {
                System.out.println(day.name());
            }
        }
    }
    class java.util.RegularEnumSet
    [MONDAY, FRIDAY]
    MONDAY
    FRIDAY
  • EnumSet<E> range(E from, E to)

    지정된 두 enum 상수 사이의 모든 상수를 포함하는 EnumSet을 반환한다. 반환된 EnumSet에는 파라미터 자체가 포함된다. 두 enum 상수 파라미터는 동일 할 수 있지만 순서가 잘못되어서는 안된다.

    순서 잘못되면 런타임 예외(IllegalArgumentException) 발생.

    class DayTest {
    
        @Test
        public void test() {
            EnumSet<Day> dayEnumSet = EnumSet.range(Day.MONDAY, Day.THURSDAY);
            System.out.println(dayEnumSet.getClass());
            System.out.println(dayEnumSet);
            for (Day day : dayEnumSet) {
                System.out.println(day.name());
            }
        }
    }
    class java.util.RegularEnumSet
    [MONDAY, TUESDAY, WEDNESDAY, THURSDAY]
    MONDAY
    TUESDAY
    WEDNESDAY
    THURSDAY

참고 : https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/EnumSet.html

Class EnumMap<K extends Enum,V>

enum과 함께 사용하기위한 특수한 Map 구현체이다.

  • EnumMap의 모든 요소는 EnumMap을 만들 때 지정된 enum type에서 가져와야한다.
  • Null을 허용하지 않는다. (Null 삽입 요청 시 NullPointerException)
  • 멀티쓰레드 프로그래밍에서 동기화 되지 않는다. (외부 동기화 필요)

생성자 살펴보기

  • EnumMap(Class<K> keyType)

    지정된 파라미터로 key type을 가지는 비어있는 EnumMap을 만든다.

  • EnumMap(EnumMap<K,? extends V> m)

    지정된 EnumMap과 같은 key type을 가지고 동일한 매핑을 포함한(존재한다면) EnumMap을 만든다.

  • EnumMap(Map<K,? extends V> m)

    지정된 Map에서 초기화 된 EnumMap을 반환한다. 새 EnumMap의 enum type을 결정하기 위해 지정된 Map에는 하나 이상의 매핑이 포함되어있어야한다. (비어있는 Map인 경우 IllegalArgumentException 예외 발생)

    class DayTest {
    
        @Test
        public void test() {
            String a = "hello a";
            String b = "hello b";
            String c = "hello c";
    
            Map map = new HashMap<Enum, String>();
            map.put(Day.MONDAY, a);
            map.put(Day.TUESDAY, b);
            map.put(Day.WEDNESDAY, c);
    
            EnumMap enumMap = new EnumMap(map);
        }
    }

메소드 살펴보기

  • int size()

    EnumMap의 모든 key-value 매핑 수를 반환한다.

  • void clear()

    EnumMap의 모든 매핑을 제거한다.

  • boolean containsKey(Object Key)

    EnumMap에 지정된 key에 대한 매핑이 포함되어있는 경우 true를 반환한다.

  • boolean containsValue(Object value)

    EnumMap에 지정된 value에 대한 매핑이 포함되어있는 경우 true를 반환한다.

  • Set<Map.Entry<K,V>> entrySet()

    EnumMap에 포함되어 있는 key-value 쌍들로 Set을 만들어 반환한다.

  • V get(Object key)

    EnumMap에서 지정된 key 에 매핑되어 있는 value를 반환한다.

    해당 key가 없으면 null을 반환한다.

    (null이 반환된다고 해서 key가 없다는 것은 아닐 수 있다. key에 명시적으로 null이 맵핑되어 있을수도 있기 때문. )

  • Set<K> keySet()

    EnumMap에 포함되어 있는 key들로 Set을 만들어 반환한다.

  • V put(K key, V value)

    EnumMap에 새로운 key-value 매핑을 추가합니다. 만약 지정된 key가 이미 존재하는 경우 value를 대체한다.

  • putAll(Map<? extends K,? extends V> m)

    지정된 Map의 모든 매핑을 EnumSet으로 복사합니다. 동일한 key가 있는 경우 매핑을 대체한다.

  • V remove(Object key)

    EnumMap에서 지정된 key가 존재한다면 해당하는 매핑을 제거한다.

  • Collection<V> values()

    EnumMap에 포함되어 있는 value들로 Collection을 만들어 반환한다.\

import org.junit.jupiter.api.Test;

import java.util.*;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;

class DayTest {

    @Test
    public void test() {
        String a = "hello a";
        String b = "hello b";
        String c = "hello c";

        EnumMap enumMap = new EnumMap(Day.class);
        enumMap.put(Day.MONDAY, a);
        enumMap.put(Day.TUESDAY, b);
        enumMap.put(Day.WEDNESDAY, c);

        assertThat(enumMap.size()).isEqualTo(3);

        assertThat(enumMap.containsKey(Day.MONDAY)).isTrue();

        assertThat(enumMap.containsValue("hello c")).isTrue();

        enumMap.put(Day.TUESDAY, "hello B");

        assertThat(enumMap.get(Day.TUESDAY)).isEqualTo("hello B");

        enumMap.remove(Day.TUESDAY);

        assertThat(enumMap.keySet()).doesNotContain(Day.TUESDAY);

        assertThat(enumMap.values()).doesNotContain("hello B");

        EnumMap copyMap = new EnumMap(enumMap);
        enumMap.clear();

        enumMap.putAll(copyMap);
        assertThat(enumMap.size()).isEqualTo(2);

    }
}

참고 : https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/EnumMap.html

Comments