Java中的EnumMap类

Java中的EnumMap类

EnumMap是枚举类型的Map接口的专门实现。它扩展了AbstractMap并在Java中实现了Map接口。它属于java.util包。EnumMap的一些重要特点如下:

  • EnumMap类是Java集合框架的成员,并且不同步。
  • EnumMap是一个有序的集合,它们以它们的键的自然顺序维护(键的自然顺序是指在枚举类型中声明枚举常量的顺序)
  • 它是一个高性能的Map实现,比HashMap要快得多。
  • 每个EnumMap实例的所有键都必须是单个枚举类型的键。
  • EnumMap不允许空键,当我们尝试插入空键时,它会抛出NullPointerException。
  • 集合视图返回的迭代器是弱一致性的:它们永远不会抛出ConcurrentModificationException,它们可能或可能不会显示在迭代正在进行时发生的任何对Map的修改的影响。
  • EnumMap在内部表示为数组。 这种表示非常紧凑和高效。

语法: 声明

public class EnumMap<K extends Enum<K>,V> extends AbstractMap<K,V> implements Serializable, Cloneable

参数:

  • 键对象类型
  • 值对象类型

K 必须扩展Enum,这使得键必须是指定的枚举类型的要求得到执行。

Java中的EnumMap类是专门为枚举键而设计的一种专用的Map实现。 EnumMap是使用HashMap与枚举键的紧凑,高效,快速的替代品。

下面是如何在Java中使用EnumMap类的示例:

import java.util.EnumMap;
 
enum Days {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
 
public class EnumMapExample {
    public static void main(String[] args) {
        EnumMap<Days, String> schedule = new EnumMap<>(Days.class);
         
        // 将元素添加到EnumMap
        schedule.put(Days.MONDAY, "Work");
        schedule.put(Days.TUESDAY, "Work");
        schedule.put(Days.WEDNESDAY, "Study");
        schedule.put(Days.THURSDAY, "Study");
        schedule.put(Days.FRIDAY, "Relax");
         
        // 从EnumMap获取元素
        System.out.println(schedule.get(Days.MONDAY)); // 输出:Work
        System.out.println(schedule.get(Days.FRIDAY)); // 输出:Relax
    }
}

输出:

Work

Relax

在这个例子中,我们定义了一个代表星期几的枚举类型Days。然后我们创建一个EnumMap并使用put方法向其中添加元素。最后,我们使用get方法从EnumMap检索元素并将结果打印到控制台。

使用EnumMap的优点:

  1. 高效:EnumMap类快速高效地访问存储在Map中的元素,使其成为性能关键型应用程序的良好选择。
  2. 紧凑:EnumMap类使用紧凑的表示形式表示Map,这意味着它需要的内存比HashMap或TreeMap要少。
  3. 类型安全:EnumMap类只允许指定枚举类型的键,这意味着它提供类型安全行为并消除了需要进行类型转换的需要。
  4. 排序键:EnumMap类提供排序键,这意味着Map中的元素按照枚举常量声明的顺序排列。

使用EnumMap的缺点:

  1. 仅限于使用枚举作为键:EnumMap类仅能用于枚举类型的键,这意味着它不适用于其他类型的键。
  2. 键不可变:EnumMap类使用枚举键,它们是不可变的,一旦创建便不能修改。

EnumMap层次结构

Java中的EnumMap类

EnumMap构造函数

  1. EnumMap(Class keyType): 构造函数用于创建一个指定键类型的空EnumMap。
  2. EnumMap(EnumMap m): 构造函数用于创建一个枚举映射表,其键类型与指定枚举映射表相同,初始映射也与EnumMap相同。
  3. EnumMap(Map m): 构造函数用于从指定参数中的映射初始化枚举映射表。

示例

// Java Program to illustrate Working of EnumMap class
// and its functions

// Importing EnumMap class
import java.util.EnumMap;

// Main class
public class EnumMapExample {

    // Enum
    public enum GFG {
        CODE,
        CONTRIBUTE,
        QUIZ,
        MCQ;
    }

    // Main driver method
    public static void main(String args[])
    {

        // Java EnumMap
        // Creating an empty EnumMap with key
        // as enum type state
        EnumMap<GFG, String> gfgMap
            = new EnumMap<GFG, String>(GFG.class);

        // Putting values inside EnumMap in Java
        // Inserting Enum keys different from
        // their natural order
        gfgMap.put(GFG.CODE, "Start Coding with gfg");
        gfgMap.put(GFG.CONTRIBUTE, "Contribute for others");
        gfgMap.put(GFG.QUIZ, "Practice Quizes");
        gfgMap.put(GFG.MCQ, "Test Speed with Mcqs");

        // Printing size of EnumMap
        System.out.println("Size of EnumMap in java: "
                                   + gfgMap.size());

        // Printing Java EnumMap
        // Print EnumMap in natural order
        // of enum keys (order on which they are declared)
        System.out.println("EnumMap: " + gfgMap);

        // Retrieving value from EnumMap
        System.out.println("Key : " + GFG.CODE + " Value: "
                                   + gfgMap.get(GFG.CODE));

        // Checking if EnumMap contains a particular key
        System.out.println(
            "Does gfgMap has " + GFG.CONTRIBUTE + ": "
            + gfgMap.containsKey(GFG.CONTRIBUTE));

        // Checking if EnumMap contains a particular value
        System.out.println(
            "Does gfgMap has :" + GFG.QUIZ + " : "
            + gfgMap.containsValue("Practice Quizes"));
        System.out.println("Does gfgMap has :" + GFG.QUIZ
                                   + " : "
                                   + gfgMap.containsValue(null));
    }
}

输出

Size of EnumMap in java: 4
EnumMap: {CODE=Start Coding with gfg, CONTRIBUTE=Contribute for others, QUIZ=Practice Quizes, MCQ=Test Speed with Mcqs}
Key : CODE Value: Start Coding with gfg
Does gfgMap has CONTRIBUTE: true
Does gfgMap has :QUIZ : true
Does gfgMap has :QUIZ : false

EnumMap的基本操作

操作1: 添加元素

为了向EnumMap中添加元素,我们可以使用put()或putAll()方法,如下所示。

// Java Program to Remove Elements from EnumMap
 
// Importing required classes
import java.util.EnumMap;
 
// Main class
// RemoveElementsFromEnumMap
class GFG {
 
    // Enum
    enum Color { RED, GREEN, BLUE, WHITE }
 
    // Main driver method
    public static void main(String[] arg)
    {
 
        // Creating an EnumMap of the Color enum
        EnumMap<Color, Integer> colors
            = new EnumMap<>(Color.class);
 
        // Inserting elements using put() method
        colors.put(Color.RED, 1);
        colors.put(Color.GREEN, 2);
        colors.put(Color.BLUE, 3);
        colors.put(Color.WHITE, 4);
 
        // Printing elements of the map
        System.out.println("EnumMap before removal : " + colors);
 
        // Removing elements using remove() method
        colors.remove(Color.BLUE);
        System.out.println("EnumMap after removal of BLUE : " + colors);
 
        // Removing elements using removeAll() method
        colors.removeAll(colors);
        System.out.println("EnumMap after invoking removeAll() : " + colors);
    }
}

输出

EnumMap before removal : {RED=1, GREEN=2, BLUE=3, WHITE=4}
EnumMap after removal of BLUE : {RED=1, GREEN=2, WHITE=4}
EnumMap after invoking removeAll() : {}
// Java程序:删除EnumMap元素
 
// 导入EnumMap类
import java.util.EnumMap;
 
// 主类
class GFG {
 
    // 枚举
    enum Color {
 
        // 自定义元素
        RED,
        GREEN,
        BLUE,
        WHITE
    }
 
    // 主方法
    public static void main(String[] args)
    {
 
        // 创建颜色枚举的EnumMap
        EnumMap<Color, Integer> colors
            = new EnumMap<>(Color.class);
 
        // 使用put()方法在Map中插入元素
        colors.put(Color.RED, 1);
        colors.put(Color.GREEN, 2);
        colors.put(Color.BLUE, 3);
        colors.put(Color.WHITE, 4);
 
        // 在控制台输出EnumMap中的颜色
        System.out.println("EnumMap colors : " + colors);
 
        // 使用remove()方法去除一个mapping
        int value = colors.remove(Color.WHITE);
 
        // 显示删除的值
        System.out.println("Removed Value: " + value);
 
        // 删除特定颜色并存储布尔值,显示是否删除
        boolean result = colors.remove(Color.RED, 1);
 
        // 将该布尔值打印到控制台
        System.out.println("Is the entry {RED=1} removed? "
                           + result);
 
        // 打印更新后的Map到控制台
        System.out.println("Updated EnumMap: " + colors);
    }
}

输出

EnumMap colors : {RED=1, GREEN=2, BLUE=3, WHITE=4}
Removed Value: 4
Is the entry {RED=1} removed? true
Updated EnumMap: {GREEN=2, BLUE=3}

操作4: 替换元素

Map接口提供了三种替换EnumMap映射的方式。

示例

// Java程序:替换EnumMap元素
 
// 导入所需类
import java.util.EnumMap;
 
// 主类
class GFG {
 
    // 枚举
    enum Color {
 
        RED,
        GREEN,
        BLUE,
        WHITE
    }
 
    // 主方法
    public static void main(String[] args)
    {
 
        // 创建颜色枚举的EnumMap
        EnumMap<Color, Integer> colors
            = new EnumMap<>(Color.class);
 
        // 使用put()方法将元素插入Map中
        colors.put(Color.RED, 1);
        colors.put(Color.GREEN, 2);
        colors.put(Color.BLUE, 3);
        colors.put(Color.WHITE, 4);
 
        // 在控制台输出map中的所有元素
        System.out.println("EnumMap colors " + colors);
 
        // 替换表示颜色的某些元素
        colors.replace(Color.RED, 11);
        colors.replace(Color.GREEN, 2, 12);
 
        // 打印更新后的元素
        System.out.println("EnumMap using replace(): "
                           + colors);
 
        // 使用replaceAll()方法替换所有颜色
        colors.replaceAll((key, oldValue) -> oldValue + 3);
 
        // 打印上述Map的所有元素
        System.out.println("EnumMap using replaceAll(): "
                           + colors);
    }
}

输出

EnumMap colors {RED=1, GREEN=2, BLUE=3, WHITE=4}
EnumMap using replace(): {RED=11, GREEN=12, BLUE=3, WHITE=4}
EnumMap using replaceAll(): {RED=14, GREEN=15, BLUE=6, WHITE=7}

同步EnumMap

EnumMap的实现是不同步的。这意味着如果多个线程同时访问一个树集合,而至少有一个线程修改了集合,那么它必须在外部进行同步。通常可以通过使用Collections类的synchronizedMap()方法来实现。最好在创建时完成此操作,以防止意外的非同步访问。

Map<EnumKey, V> m = Collections.synchronizedMap(new EnumMap<EnumKey, V>(...));

EnumMap的方法

  • K – 键对象的类型
  • V – 值对象的类型
方法 行为
clear() 删除此映射中的所有映射。
clone() 返回此枚举映射的浅表副本。
containsKey​(Object key) 如果此映射包含指定键的映射,则返回true。
containsValue​(Object value) 如果此映射将一个或多个键映射到指定值,则返回true。
entrySet() 返回此映射中所包含的映射的 Set 视图。
equals​(Object o) 比较指定对象与此映射的相等性。
get​(Object key) 返回指定键所映射的值,如果此映射不包含该键的映射,则返回null。
hashCode() 返回此映射的哈希码值。
keySet() 返回此映射中所包含的键的 Set 视图。
put​(K key, V value) 在此映射中将指定值与指定键关联。
putAll​(Map<? extends K,​? extends V> m) 将指定映射中的所有映射复制到此映射中。
remove​(Object key) 从此映射中删除指定键的映射(如果存在)。
size() 返回此映射中键-值映射关系的数量。
values() 返回此映射中包含的值的 Collection 视图。

在AbstractMap类中声明的方法

方法 描述
isEmpty() 如果此映射未包含键值映射,则返回true。
toString() 返回此Map的字符串表示形式。

在接口java.util.Map中声明的方法

本文涉及了 EnumMap 类的方法以及 AbstractMap 和 java.util.Map 接口中声明的方法。在使用 EnumMap 时,需要注意其实现是不同步的,并且多线程同时访问时需要进行外部同步。通常可以通过使用 Collections 类中的 synchronizedMap() 方法进行同步。此外,本文中还介绍了 EnumMap 类中的各种方法以及在 AbstractMap 类和 java.util.Map 接口中声明的方法,供读者参考。

方法 描述
compute​(K key, BiFunction<? super K,​? super V,​? extends V> remappingFunction) 尝试计算指定键及其当前映射值(如果当前没有映射则为null)的映射。
computeIfAbsent​(K key, Function<? super K,​? extends V> mappingFunction) 如果指定的键没有关联值(或映射为null),则尝试使用给定的映射函数计算其值并将其输入到该映射中,除非null。
computeIfPresent​(K key, BiFunction<? super K,​? super V,​? extends V> remappingFunction) 如果指定键的值存在且不为null,则尝试计算给定键及其当前映射值的新映射。
forEach​(BiConsumer<? super K,​? super V> action) 对该映射中的每个条目执行给定的操作,直到所有条目都被处理或操作引发异常。
getOrDefault​(Object key, V defaultValue) 返回指定键映射到的值,如果该映射不包含该键的映射,则返回defaultValue。
merge​(K key, V value, BiFunction<? super V,​? super V,​? extends V> remappingFunction) 如果指定键尚未与值关联或者已关联null,则将其关联为给定的非null值。
putIfAbsent​(K key, V value) 如果指定键尚未关联值(或映射为null),则将其关联为给定的值并返回null,否则返回当前值。
remove​(Object key, Object value) 仅当指定键当前映射到指定值时,才删除该键的条目。
replace​(K key, V value) 仅当指定键当前映射到某个值时,才替换该键的条目。
replace​(K key, V oldValue, V newValue) 仅当指定键当前映射到指定值时,才替换该键的条目。
replaceAll​(BiFunction<? super K,​? super V,​? extends V> function) 使用对每个条目调用该函数的结果替换每个条目的值,直到所有条目都被处理或函数抛出异常。

EnumMap vs EnumSet

属性 EnumMap EnumSet
内部表示 EnumMap是以数组的形式进行内部表示的。该表示方法紧凑高效。 EnumSet是以位向量或位序列作为内部表示的。
允许空元素吗? 不允许使用空键,但允许使用空值。 不允许使用空元素。
是否为抽象类?
实例化 由于EnumMap不是抽象类,可以使用new运算符进行实例化。 它是一个抽象类,没有构造函数。使用其预定义的方法(如allOf()、noneOf()、of()等)创建枚举集。
实现 EnumMap是专为枚举类型键设计的特殊Map实现。 EnumSet是专为枚举类型设计的特殊Set实现。

示例:

解释

EnumMap是Java中Map接口的专门指定实现,旨在与枚举作为键一起使用。它是一种高性能的实现,可以保证在许多基本操作(如get()和put())中具有常数时间性能。

EnumMap类是一个强类型的Map实现,这意味着它只能与枚举作为键一起使用。EnumMap的每个实例都与特定的枚举类相关联,map的键集是枚举值的一个子集。这确保了键始终是独特且定义明确的。

使用EnumMap的主要优势之一是其性能。由于它是专门为枚举使用而设计的,因此可以优化以利用枚举的独特属性。例如,EnumMap实现使用紧凑的基于数组的数据结构,为许多基本操作提供了常数时间性能。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程