Java编程思想15

使用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 java.util.EnumSet;

import static enumerated.AlarmPoints.*;

/**
* @author Mr.Sun
* @date 2022年09月02日 17:18
*/
public class EnumSetTest {
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);
}
}

 

 

使用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.*;

/**
* @author Mr.Sun
* @date 2022年09月02日 17:25
*
* 使用EnumMap
*/
interface Command{ void action(); }

public class EnumMapTest {
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 {
// If there's no value for a particular key:
em.get(UTILITY).action();
} catch(Exception e) {
System.out.println(e);
}
}
}/* Output:
BATHROOM: Bathroom alert!
KITCHEN: Kitchen fire!
java.lang.NullPointerException
*///:~

与EnumSet一样,enum实例定义时的次序决定了其在EnumMap中的顺序。
  main()方法的 最后部分说明,enum的每个实例作为一个键,总是存在的,但是如果你没有为这个键调用put()方法来存入相应的值的话,对应的值就是null。

常量相关的方法
  Java的Enum有一个非常有趣的特性,即它允许程序员为enum实例编写方法,从而为每个enum实例赋予各自不同的行为,要实现常量相关的方法,你需要为enum定义一个或多个abstract方法,然后为每个enum实例实现该抽象方法。参考下面的例子:

package enumerated;

import java.text.DateFormat;
import java.util.Date;

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 csm : values()) {
System.out.println(csm.getInfo());
}
}
}/* Output:
2022-9-2
null
1.8.0_211
*///:~

 

posted @   就叫清风吧  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示