Tìm hiểu EnumMap trong Java

EnumMap là một Map implementation được thiết kế để làm việc với kiểu dữ liệu Enum trong Java. Trong bài viết này chúng ta sẽ cùng nhau tìm hiểu về nó, cũng như một số trường hợp sử dụng cơ bản, và khi nào thì nên sử dụng EnumMap.

Project Setup

Hãy tưởng tượng một yêu cầu đơn giản trong đó chúng ta cần lập bản đồ các ngày trong tuần với môn thể thao chúng ta chơi vào ngày đó:

 

Monday     Soccer                         
Tuesday    Basketball                     
Wednesday  Hiking                         
Thursday   Karate

Do vậy, chúng ta cần cần tạo một Enum 

public enum DayOfWeek {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

Khởi tạo EnumMap

Để khởi tạo EnumMap với enum là DayOfWeek enum 

EnumMap<DayOfWeek, String> activityMap = new EnumMap<>(DayOfWeek.class);
activityMap.put(DayOfWeek.MONDAY, "Soccer");

Đây là điểm khác biệt đầu tien so với những Map implementation khác như HashMap. Lưu ý rằng với HashMap chúng ta có thể khởi tạo new HashMap<>(). Tuy nhiên, EnumMap yêu cầu kiểu dữ liệu của key trong quá trình khởi tạo.

EnumMap copy constructor

EnumMap cũng có hai trình tạo bản sao. Đầu tiên lấy một EnumMap khác: Đầu tiên lấy một EnumMap khác

EnumMap<DayOfWeek, String> activityMap = new EnumMap<>(DayOfWeek.class);
activityMap.put(DayOfWeek.MONDAY, "Soccer");
activityMap.put(DayOfWeek.TUESDAY, "Basketball");

EnumMap<DayOfWeek, String> activityMapCopy = new EnumMap<>(activityMap);
assertThat(activityMapCopy.size()).isEqualTo(2);
assertThat(activityMapCopy.get(DayOfWeek.MONDAY)).isEqualTo("Soccer");
assertThat(activityMapCopy.get(DayOfWeek.TUESDAY)).isEqualTo("Basketball")

Map Copy Constructor

Hoặc, nếu chúng ta có một Map không rỗng và có khóa là enum, thì chúng ta cũng có thể làm điều đó:
 
Map<DayOfWeek, String> ordinaryMap = new HashMap();
ordinaryMap.put(DayOfWeek.MONDAY, "Soccer");

EnumMap enumMap = new EnumMap(ordinaryMap);
assertThat(enumMap.size()).isEqualTo(1);
assertThat(enumMap.get(DayOfWeek.MONDAY)).isEqualTo("Soccer");

Lưu ý rằng Map không được rỗng tất là nó phải chứa ít nhất một phần tử để EnumMap có thể xác định được kiểu dữ liệu của key từ một phần tử đã tồn tại trong Map.

Thêm và truy xuất phần tử trong EnumMap

Sau khi khởi tạo một EnumMap, chúng ta có thể thêm phần tử vào thông qua put() method.

activityMap.put(DayOfWeek.MONDAY, "Soccer");

Và để truy xuất một phần tử trong EnumMap chúng ta phải sử dụng đến get() method nhận vào một key và trả về value tương ứng.

assertThat(clubMap.get(DayOfWeek.MONDAY)).isEqualTo("Soccer");

Kiểm tra phần tử

Để kiểm tra xem chúng ta có một ánh xạ được xác định cho một ngày cụ thể hay không, chúng tôi sử dụng hàm containsKey ():

activityMap.put(DayOfWeek.WEDNESDAY, "Hiking");
assertThat(activityMap.containsKey(DayOfWeek.WEDNESDAY)).isTrue();

Và để kiểm tra có chứa một value bất kỳ hay không chúng ta có thể sử dụng containsValue().

assertThat(activityMap.containsValue("Hiking")).isTrue();

Value Null

Một key có chứa value là NULL được xem là hợp lệ trong EnumMap

assertThat(activityMap.containsKey(DayOfWeek.SATURDAY)).isFalse();
assertThat(activityMap.containsValue(null)).isFalse();
activityMap.put(DayOfWeek.SATURDAY, null);
assertThat(activityMap.containsKey(DayOfWeek.SATURDAY)).isTrue();
assertThat(activityMap.containsValue(null)).isTrue();

Xoá phần tử

Để xoá một phần tử ra khỏi EnumMap chúng ta có thể sử dụng remove() method

activityMap.put(DayOfWeek.MONDAY, "Soccer");
assertThat(activityMap.remove(DayOfWeek.MONDAY)).isEqualTo("Soccer");
assertThat(activityMap.containsKey(DayOfWeek.MONDAY)).isFalse();

Như chúng ta có thể quan sát, remove (key) trả về giá trị trước đó được liên kết với key hoặc null nếu không có ánh xạ cho key.

Chúng ta cũng có thể xoá dựa vào một cặp key-value cụ thể tương ứng trong EnumMap.

activityMap.put(DayOfWeek.Monday, "Soccer");
assertThat(activityMap.remove(DayOfWeek.Monday, "Hiking")).isEqualTo(false);
assertThat(activityMap.remove(DayOfWeek.Monday, "Soccer")).isEqualTo(true);

Method remove (key, value) chỉ xóa phần tử nếu tồn tại một phần có key và value tương ứng với tham số truyền vào.

Collection Views

Để liệt kê một danh sách các key hoặc value trong EnumMap chúng ta có thể thực thi bằng những cách được mô tả ở các phần sau. Trước tiên, chúng ta cần khởi tạo một EnumMap dùng cho các ví dụ bên dưới.

EnumMap<DayOfWeek, String> activityMap = new EnumMap(DayOfWeek.class);
activityMap.put(DayOfWeek.THURSDAY, "Karate");
activityMap.put(DayOfWeek.WEDNESDAY, "Hiking");
activityMap.put(DayOfWeek.MONDAY, "Soccer");

values

Hàm values() trả về tất cả các value được lưu trữ trong EnumMap.

Collection values = dayMap.values();
assertThat(values)
  .containsExactly("Soccer", "Hiking", "Karate");

Lưu ý ở đây rằng EnumMap là một Map có thứ tự, Nó sử dụng thứ tự của enum DayOfWeek để xác định thứ tự của các phần tử. 

keySet

Tương tự, keySet() trả về danh sách các key trong EnumMap, thứ tự trả về được sắp xếp theo Enum.

Set keys = dayMap.keySet();
assertThat(keys)
        .containsExactly(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY, DayOfWeek.SATURDAY);

entrySet

Cuối cùng entrySet trả về danh sách cặp key-value trong EnumMap

assertThat(dayMap.entrySet())
    .containsExactly(
        new SimpleEntry(DayOfWeek.MONDAY, "Soccer"),
        new SimpleEntry(DayOfWeek.WEDNESDAY, "Hiking"),
        new SimpleEntry(DayOfWeek.THURSDAY, "Karate")
    );

Mutability

Bây giờ, hãy nhớ rằng bất kỳ thay đổi nào chúng ta thực hiện trong EnumMap sẽ ảnh hưởng đến thứ tự sắp xếp của các phần tử.

Ví dụ khi chúng ta thêm DayOfWeek.TUESDAY vào EnumMap thì nó sẽ được xếp sau DayOfWeek.MONDAY và DayOfWeek.WEDNESDAY nhưng lại trước DayOfWeek.THURSDAY.

activityMap.put(DayOfWeek.TUESDAY, "Basketball");
assertThat(values)
    .containsExactly("Soccer", "Basketball", "Hiking", "Karate");

Khi nào nên sử dụng EnumMap

Hiệu năng

Sử dụng Enum làm key giúp bạn có thể thực hiện một số tối ưu hóa hiệu suất bổ sung, chẳng hạn như tính toán băm nhanh hơn vì tất cả các key khả thi đều được biết trước.

Sử dụng Enum làm key giúp EnumMao chỉ cần sử dụng một mảng thuần tuý trong Java để lưu trữ và truy xuất trong khi các Map implementation khác cần một cấu trúc khác phức tạp hơn để lưu trữ các key có kiểu generic type. Ví dụ, HashMap cần một cấu trúc dữ liệu phức tạp và một logic lưu trữ và truy xuất phức tạp hơn đáng kể để phục vụ cho khả năng xảy ra xung đột băm.

Chức năng

Ngoài ra, như chúng ta đã thấy, EnumMap là một Map có thứ tự, trong đó các dữ liệu của nó sẽ được sắp xếp theo thứ tự enum. Để có được hành vi tương tự cho các tình huống phức tạp hơn, chúng ta có thể TreeMap và LinkedHashMap.

Kết bài

Trong bài viết này, chúng ta đã khám phá cách triển khai EnumMap của Map interface Khi làm việc với Enum làm key, EnumMap có thể hữu ích trong những trường hợp như vậy.

Nguồn tham khảo

https://www.baeldung.com/java-enum-map

 

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x