首页 > 代码库 > EnumSet的最佳实践

EnumSet的最佳实践

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

int interestSet = selectionKey.interestOps();
boolean isInterestedInAccept  = (interestSet & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT;
boolean isInterestedInConnect = (interestSet & SelectionKey.OP_CONNECT)== SelectionKey.OP_CONNECT;
boolean isInterestedInRead    = (interestSet & SelectionKey.OP_READ)== SelectionKey.OP_READ;boolean isInterestedInWrite   = (interestSet & SelectionKey.OP_WRITE)== SelectionKey.OP_WRITE;

这段代码是不是看的有点头晕,并且当一个interestSet包含多个你事件时你就等着就去写长长的if else表达式吧,现在如果把这种情景换成EnumSet会是如何呢:

首先定义一个Enum类,还拿nio来举例,定义了几种通道可能感兴趣的事件(accept,connect,read,write):

enum SelectionKey{
OP_ACCEPT,OP_CONNECT,OP_READ,OP_WRITE
}

那么如果我们现在要一个对accept和connect事件感兴趣的interestSet我们只需要下面一行代码:
EnumSet<SelectionKey> interestSet = EnumSet.of(OP_ACCEPT,OP_CONNECT);
那么如何判断这个集合是否包含一个特定的操作呢?!别忘了我们的EnumSet继承了Set接口,Set接口提供了一个contains方法

interestSet.contains(SlectionKey.OP_READ);    //false

如何遍历EnumSet?自行举一反三。
神马?你在担心性能?放心,EnumSet的底层是一个8byte的long型,一共64bit,这是啥意思呢,熟悉Enum的javaer都知道,Enum里面定义实例的顺序是敏感的,java.lang.Enum提供了一个ordinal方法,它会返回一个int值,代表这个enum实例在类里被定义的顺序,比如如果我调用SelectionKey的OP_ACCEPT的ordinal方法,那么它会返回1,现在回到EnumSet,上面我们定义了一个interestSet,里面包含了OP_ACCEPT和OP_CONNECT这两种我们感兴趣的操作,那么EnumSet的底层long的值为110000....(此处补齐64bit),如果你的Enum类定义的实例超过了64个,那么EnumSet会自动扩增!所以以后你可以尽请的使用Enum和EnumSet来代替位域操作啦!