enum,EnumMap,EnumSet

enum基本使用

package com.enumTest;

enum Shrubbery {

GROUND, CRAWLING, HANGING}

public class EnumClass {

public static void main(String[] args) {

for (Shrubbery s : Shrubbery.values()) {

System.out.println(s + “ordinal:” + s.ordinal());

System.out.println(s.compareTo(Shrubbery.CRAWLING) + “”);

System.out.println(s.equals(Shrubbery.CRAWLING) + “”);

System.out.println(s == Shrubbery.CRAWLING);

System.out.println(“s.getDeclaringClass:” + s.getDeclaringClass()

+ “getClass:” + s.getClass());

System.out.println(s.name());

System.out.println(“——————————-“);

}

String[] arrayString=”HANGING CRAWLING GROUND”.split(” “);

for (String s : arrayString) {

Shrubbery shrub = Enum.valueOf(Shrubbery.class, s);

System.out.println(shrub);

}

}

}

  1. 每个enum实例(GROUND, CRAWLING, HANGING)都记录一个次序original(0,1,2).

    2.实现了Comparable接口,重写了compareTo按照 original来比较次序,且仅运行同一个enum类型实例做比较.

    3.equals 比较内存地址

    4.实现了 Serializable接口.

除了少量限制,我们可以把enum当作普通类型对待:

package com.enumTest;

public enum OzWitch {

//you must define enum instances firstly.
WEST("west"), NORTH("north"), EAST("east"), SOUTH("south");
private String description;

//even if the constructor is public .. , it‘s nonsense!
private OzWitch(String description) {
    this.description = description;
}

public String getDescription() {
    return description;
}

public static void main(String[] args) {
    for (OzWitch witch : OzWitch.values()) {
        System.out.println(witch + ":" + witch.getDescription());

    }
}

}

enum 类型可以用于switch 语句中

.switch(integer or enum){

case ….

}

enum Signal {

GREEN, YELLOW, RED

}

public class TrafficLight {

Signal color = Signal.RED;

public void change() {
    switch (color/*枚举实例*/) {
    //case ** 被强制用color类型的实例
    case RED:
        color = Signal.GREEN;
        break;
    case GREEN:
        color = Signal.YELLOW;
        break;
    case YELLOW:
        color = Signal.RED;
        break;
    }
}
public String toString() {
    return "The traffic light is " + color;
}

public static void main(String[] args) {
    TrafficLight t = new TrafficLight();
    for (int i = 0; i < 7; i++) {
        System.out.println(t);
        t.change();
    }
}

}

关键字 enum 与 java.lang.Enum 的区别:

我们看以下代码:

enum Explore { HERE, THERE }

public class Reflection {

public static Set analyze(Class

package com.enumTest;

//枚举中的枚举

public enum Course {

//定义三个枚举实例

APPETIZER(Food.Appetizer.class),

MAINCOURSE(Food.MainCourse.class),

COFFEE(Food.Coffee.class);

//定一个域 用来得到 每个实例中包含的实例

private Food[] allFood;

//构造器获得一个枚举类型中的所有实例
//这个构造器 ,通过入参获取该入参对应的所有实例
Course(Class<? extends Food> clazz) {
    allFood = clazz.getEnumConstants();
}
//随机获取一个枚举(如 APPETIZER)中的枚举实例(如 SALAD,SOUP,RED_WINE)中的一个
public Food randomSelection() {
    return Enums.random(allFood);
}

public static void main(String[] args) {

for (int i = 0; i < Course.values().length; i++) {

for (Course course : Course.values()) {

Food food = course.randomSelection();

System.out.println(food);

}

System.out.println(“———–”);

}

另外,还有一种简洁的组织方式(随便选择一种即可,个人倾向第一种,clear!):

public enum Meal2 {
APPETIZER(Food.Appetizer.class),
MAINCOURSE(Food.MainCourse.class),
DESSERT(Food.Dessert.class),
COFFEE(Food.Coffee.class);
private Food[] values;
private Meal2(Class<? extends Food> kind) {
736 Thinking in Java Bruce Eckel
values = kind.getEnumConstants();
}
public interface Food {
enum Appetizer implements Food {
SALAD, SOUP, SPRING_ROLLS;
}
enum MainCourse implements Food {
LASAGNE, BURRITO, PAD_THAI,
LENTILS, HUMMOUS, VINDALOO;
}
enum Dessert implements Food {
TIRAMISU, GELATO, BLACK_FOREST_CAKE,
FRUIT, CREME_CARAMEL;
}
enum Coffee implements Food {
BLACK_COFFEE, DECAF_COFFEE, ESPRESSO,
LATTE, CAPPUCCINO, TEA, HERB_TEA;
}
}
public Food randomSelection() {
return Enums.random(values);
}
public static void main(String[] args) {
for(int i = 0; i < 5; i++) {
for(Meal2 meal : Meal2.values()) {
Food food = meal.randomSelection();
System.out.println(food);
}
System.out.println("---");
}
}
} /* Same output as Meal.java *///:~

EnumSet

1.其操作比HashSet快,基于long的存储

2.EnumSet 中的元素 必须是 enum类型,初始化后元素的顺序与enum实例定义顺序一致

import java.util.EnumSet;

public class EnumSets {
    public static void main(String[] args) {
        EnumSet<AlarmPoints> points = EnumSet.noneOf(AlarmPoints.class);
        points.add(AlarmPoints.BATHROOM);
        System.out.println(points);

        points.addAll(EnumSet.of(AlarmPoints.STAIR1, AlarmPoints.STAIR2,
                AlarmPoints.KITCHEN));
        System.out.println(points);

        points = EnumSet.allOf(AlarmPoints.class);
        // points.removeAll(EnumSet.of(AlarmPoints.STAIR1,AlarmPoints.STAIR2,AlarmPoints.KITCHEN));
        System.out.println(points);

        // 参数 rangefrom,rangeTo 都包含
        points.removeAll(EnumSet.range(AlarmPoints.STAIR1, AlarmPoints.STAIR2));
        System.out.println(points);

        //求一个差集
        points = EnumSet.complementOf(points);
        System.out.println(points);
    }
}

EnumSet基于long(64bit)构造, 通过EnumSet result = noneOf(elementType);初始化,EnumSet中的元素用一个bit来表示其存在。所以,如果初始化的enum元素个数超过64个则会增加long个数,如果小于64个,则会只有一个long的内存空间。

(如源码: elements 用来存元素)

/**

* Bit vector representation of this set. The 2^k bit indicates the

* presence of universe[k] in this set.

*/

private long elements = 0L;

EnumMap

1.key 必须是一个指定(构造器初始)的enum的实例,内部由数组实现,速度快

2.初始化后元素的顺序与enum实例定义顺序一致,其他操作与Map类似

3.实现 多路分发( multiple dispatching)

//命令模式 1.通常有一个仅有一个单一方法的接口
interface Command {
    void action();
}

public class EnumMaps {
    public static void main(String[] args) {
        EnumMap<AlarmPoints, Command> em = new EnumMap<AlarmPoints, Command>(
                AlarmPoints.class);

        //em 的键只允许是初始化定义的   AlarmPoints.class 的实例
        em.put(AlarmPoints.KITCHEN, new Command() {
            // 命令模式 2. 从该接口实现有各自不同行为的 子实现
            @Override
            public void action() {
                System.out.println("Kitchen Fire!");
            }
        });
        em.put(AlarmPoints.BATHROOM, new Command() {
            @Override
            public void action() {
                System.out.println("Bathroom Fire!");
            }
        });
        for(Map.Entry<AlarmPoints,Command> e:em.entrySet()){
            System.out.println("  e.getKey()  " +e.getKey());
            e.getValue().action();
        }
        try {
            em.get(AlarmPoints.UTILITY).action();
        } catch (Exception e ) {
            e .printStackTrace();
        }
    }
}

常量指定方法 (constantspecific methods)


public enum ConstantSpecificMethod {

    DATE_TIME {
        String getInfo() {
            return DateFormat.getDateInstance().format(new Date());
        }
    },
    CLASSPATH {
        String getInfo() {
            return System.getenv("CLASSPATH");
        }
    },
    VERSION {
        String getInfo() {
            return System.getProperty("java.version");
        }
    };
    //声明一个抽象方法(或者普通方法——默认行为方法,后边再说)
    abstract String getInfo();

    public static void main(String[] args) {
        for (ConstantSpecificMethod constantSpecMethod : values()) {
            System.out.println("\\s"+constantSpecMethod.getInfo());
        }
    }

}

这个也称为表驱动的代码(详见< Code Complete>)。与命令模式很相似,只不过命令模式的通用接口,在这里由enum类代替。

oop不同类关联不同行为,而使用常量方法,每个实例就是一个独立的类型(当然,并不等同于“类”)。上例中一个enum类似乎被当作“超类”对待,具体到每个实例通过getInfo()表现出不同的行为,多态。

enum LikeClasses {
WINKEN { void behavior() { print("Behavior1"); } },
BLINKEN { void behavior() { print("Behavior2"); } },
NOD { void behavior() { print("Behavior3"); } };
abstract void behavior();
}
public class NotClasses {
// void f1(LikeClasses.WINKEN instance) {} // Nope
} /* Output:反编译后的代码
Compiled from "NotClasses.java"
abstract class LikeClasses extends java.lang.Enum{
public static final LikeClasses WINKEN;
public static final LikeClasses BLINKEN;
public static final LikeClasses NOD;
...
*///

1.abstract class LikeClasses extends java.lang.Enum 一个抽象类

2.方法常量 就是这个抽象类的static 域( field)

**其中的抽象方法也可以换做 普通方法,那么默认赋予每个enum实例一个默认的方法:

public enum ConstantSpecificMethod {

    DATE_TIME, // 赋予默认 getInfo()
    /*
     * { String getInfo() { return DateFormat.getDateInstance().format(new
     * Date()); } },
     */
    CLASSPATH {
        String getInfo() {
            return System.getenv("CLASSPATH");
        }
    },
    VERSION {
        String getInfo() {
            return System.getProperty("java.version");
        }
    };
    String getInfo() {
        System.out.println("default");
        return null;
    };

    public static void main(String[] args) {
        for (ConstantSpecificMethod constantSpecMethod : values()) {
            System.out.println(constantSpecMethod.getInfo());
        }
    }

}
时间: 2024-09-28 16:12:07

enum,EnumMap,EnumSet的相关文章

计算机程序的思维逻辑 (51) - 剖析EnumSet

上节介绍了EnumMap,本节介绍同样针对枚举类型的Set接口的实现类EnumSet.与EnumMap类似,之所以会有一个专门的针对枚举类型的实现类,主要是因为它可以非常高效的实现Set接口. 之前介绍的Set接口的实现类HashSet/TreeSet,它们内部都是用对应的HashMap/TreeMap实现的,但EnumSet不是,它的实现与EnumMap没有任何关系,而是用极为精简和高效的位向量实现的,位向量是计算机程序中解决问题的一种常用方式,我们有必要理解和掌握. 除了实现机制,EnumS

深入理解Java枚举类型(enum)

[版权申明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/71333103 出自[zejian的博客] 关联文章: 理解Java位运算 深入理解Java类型信息(Class对象)与反射机制 本篇主要是深入对Java中枚举类型进行分析,主要内容如下: 理解枚举类型 枚举的定义 枚举实现原理 枚举的常见方法 Enum抽象类常见方法 编译器生成的Values方法与ValueOf方法 枚举与Clas

Android中是否推荐使用枚举Enum

一.Enum的产生 Java1.5中引入了枚举的语法,包括Enum,EnumSet,EnumMap等.其中Enum就是我们在C或C++中见过的枚举类型,但是Java中的枚举又比C或C++中的枚举更成熟和复杂.在Java中,枚举算是一种特殊的类,也就是class,因此它可以做很多类相关的事情,而不仅仅是定义几个枚举值 二.Android官方建议 Android官网不建议使用enums,占用内存多(Enums often require more than twice as much memory

EnumSet抽象类源码解析

EnumSet 专门为枚举类设计的集合类,所有元素必须是枚举类型 EnumSet的集合元素是有序的,内部以位向量的形成存储,因此占用内存小,效率高 不允许加入null元素 源码 package java.util; import sun.misc.SharedSecrets; public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> implements Cloneable, java

EnumSet的最佳实践

不知大家是否见过这样一种让人"眼花缭乱"的位域操作,int read = 0 << 1;int write = 0 << 2;int connect = 0<<3;最典型的就是jdk nio里的SelectionKey了,当你判断一个selectionkey所感兴趣的操作时,你不得不像下面这样写 int interestSet = selectionKey.interestOps(); boolean isInterestedInAccept  = 

java集合(二)Set集合之EnumSet详解

1.定义: 添加枚举类元素的专用集合类 2.与其他集合类区别: EnumSet内部实现不使用常见的数据结构,比如数组(ArrayList),链表(LinkedList),哈系表(HashMap.Hashtable.HashSet),红黑树(TreeMap.TreeSet)而是使用位运算完成集合的基本操作 EnumSet是抽象类,只能通过静态工厂方法构造EnumSet对象,具体如下: EnumSet<E> noneOf(Class<E> elementType):构造一个空的集合En

Java集合总览

这篇文章总结了所有的Java集合(Collection).主要介绍各个集合的特性和用途,以及在不同的集合类型之间转换的方式. Arrays Array是Java特有的数组.在你知道所要处理数据元素个数的情况下非常好用.java.util.Arrays 包含了许多处理数据的实用方法: Arrays.asList:可以从 Array 转换成 List.可以作为其他集合类型构造器的参数. Arrays.binarySearch:在一个已排序的或者其中一段中快速查找. Arrays.copyOf:如果你

Java集合类型详解

这篇文章总结了所有的Java集合(Collection).主要介绍各个集合的特性和用途,以及在不同的集合类型之间转换的方式. Arrays Array是Java特有的数组.在你知道所要处理数据元素个数的情况下非常好用.java.util.Arrays 包含了许多处理数据的实用方法: Arrays.asList:可以从 Array 转换成 List.可以作为其他集合类型构造器的参数. Arrays.binarySearch:在一个已排序的或者其中一段中快速查找. Arrays.copyOf:如果你

枚举类的学习

我一直不知道枚举有数量的差别,64个以下(包括)的的枚举是使用了RegularEnumSet,64个以上的使用了JumboEnumSet.最近看编写高质量代码这本书才发现枚举是有数量的限制,不过其实一般的项目还真用不到一个枚举类里面放这么多的枚举数量,不过既然学习了我就随便把它的源码拿出来看看吧,也弥补一下自己确实在枚举这一块的不足. 原谅我见识少,我竟然不知道有EnumMap和EnumSet枚举类的集合,这种时候就是学习的机会了.先看一下这个2个集合类的定义: public class Enu