资讯详情

枚举类型(3):使用EnumSet替代标志、使用EnumMap

一、使用EnumSet替换标志

Set它是一种只能添加不重复对象的集合。当然,enum也要求其成员是唯一的,所以enum也有集合行为。但是,因为不能从enum删除或添加元素,因此只能算是不太有用的集合。java SE5引入EnumSet,是为了通过enum以替代传统为基础,创造替代品int位标志。这种标志可以用来表示某种“开/关”信息,不过,使用这种标志,我们最终操作的只是一些bit,而不是这些bit要表达的概念,很容易写出难以理解的代码。

EnumSet设计充分考虑了速度因素,因为它必须非常高效bit标志竞争(其操作与HashSet相比之下,非常快)。就内部而言,它(可能)是一个long因此,值作为比较向量EnumSet非常快速高效。使用EnumSet其优点是,它具有更好的表达能力,在解释一个二进制位置是否存在时必担心性能。

EnumSet元素必须来自一个元素enum。下面的enum报警传感器的位置表示在建筑物内:

package enumerated;  public enum AlarmPoints {  STAIR1, STAIR2, LOBBY, OFFICE1, OFFICE2, OFFICE3, OFFICE4, BATHROOM, UTILITY, KITCHEN } 

然后,我们用EnumSet跟踪报警器的状态:

package enumerated;  import static enumerated.AlarmPoints.*;  import java.util.EnumSet;  public class EnumSets {  public static void main(String[] args) {   EnumSet<AlarmPoints> points = EnumSet.noneOf(AlarmPoints.class);// Empty set   points.add(BATHROOM);   System.out.println(points);   points.addAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));   System.out.println(points);   points = EnumSet.allOf(AlarmPoints.class);   points.removeAll(EnumSet.of(STAIR1, STAIR2, KITCHEN));   System.out.println(points);   points.removeAll(EnumSet.range(OFFICE1, OFFICE4));   System.out.println(points);   points = EnumSet.complementOf(points);   System.out.println(points);  } } 

使用static import可以简化enum常用。EnumSet方法的名称相当直观,可以查阅JDK找到文档的完整详细描述。若仔细研究EnumSet你还会发现一个有趣的地方:of()方法多次重载,不仅重载可变数量参数,还重载接收2-5个显式参数。这也是从侧面表现出来的EnumSet关注性能。因为只使用可变参数可以解决整个问题,但对比显式参数会有一点性能损失。使用当前的设计,但您只使用2到5个参数调用of()方法时,可以调用相应的重载方法((稍快一点),当您使用一个或五个以上的参数时,您将调用可变参数of()方法。请注意,如果您只使用一个参数,编译器不会构建可变参数的数组,因此与只调用一个参数的方法相比,不会有额外的性能损失。

EnumSet的基础是long,一个long值64位,而一位enum只有一个例子bit这意味着它是否存在。,不超过一个long在表达能力的情况下,你的EnumSet可以应用于最多不超过64个元素的enum。如果enum超过64个元素会发生什么?

package enumerated;  import java.util.EnumSet;  public class BigEnumSet {  enum Big {   A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22, A23,   A24, A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, A35, A36, A37, A38, A39, A40, A41, A42, A43, A44, A45,   A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, A59, A60, A61, A62, A63, A64, A65, A66, A67,   A68, A69, A70, A71, A72, A73, A74, A75  }   public static void main(String[] args) {   EnumSet<Big> bigEnumSet = EnumSet.allOf(Big.class);   System.out.println(bigEnumSet);  } } 

显然,EnumSet可应用于64多个元素enum,所以我猜,Enum必要时会增加一个long。

二、使用EnumMap

EnumMap是一种特殊的Map,它需要键(key)必须来自一个enum。由于enum所以EnumMap数组可以在内部实现。因此EnumMap速度很快,我们可以放心使用enum实例在EnumMap搜索操作。但是,我们只能做到enum用键调用实例put()其他操作和使用方法Map差不多。

下面的例子展示了命令设计模式的使用。一般来说,命令模式首先需要一个只有单一方法的接口,然后从接口中实现不同行为的多个子类。接下来,程序员可以构建命令对象命令对象并使用它们:

package enumerated;  import java.util.EnumMap; import java.util.Map;  import static enumerated.AlarmPoints.*;  interface Command {  void action(); }  public class EnumMaps {  public static void main(String[] args) {   EnumMap<AlarmPoints, Command> em = new EnumMap<>(AlarmPoints.class);   em.put(KITCHEN, () -> {    System.out.println("Kitchen fire!");   });   em.put(BATHROOM, () -> {    System.out.println("Bathroom alert!");   });   for (Map.Entry<AlarmPoints, Command> e : em.entrySet()) {    System.out.print(e.getKey()   ": ");    e.getValue().action();   }   // 若某个键没有值   try {    em.get(UTILITY).action();   } catch (Exception e1) {    e1.printStackTrace();   }  } } 

与EnumSet一样,enum实例定义中的顺序决定了它EnumMap中的顺序。

main()方法最后部分说明,enum每一个例子作为一个键总是存在的。但是,如果你不调用这个键put()存储相应值的方法,相应值为null。

与常量相关的方法(constant-specific methods与下一节相比,EnumMap有一个优点,那EnumMap允许程序员改变值对象,常量相关方法在编译期固定。

稍后你会看到,在你有多种类型的enum,我们可以使用它们之间的相互操作EnumMap实现多路分发(multiple dispatching)。

标签: 传感器352a25

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台