soa*_*rol 38 java enums enumset
我维护一个大型文档存档,我经常使用位字段来记录处理期间或验证文档时的状态.我的遗留代码只使用静态int常量,例如:
static int DOCUMENT_STATUS_NO_STATE = 0
static int DOCUMENT_STATUS_OK = 1
static int DOCUMENT_STATUS_NO_TIF_FILE = 2
static int DOCUMENT_STATUS_NO_PDF_FILE = 4
Run Code Online (Sandbox Code Playgroud)
通过设置适当的标志,可以很容易地指示文档所处的状态.例如:
status = DOCUMENT_STATUS_NO_TIF_FILE | DOCUMENT_STATUS_NO_PDF_FILE;
Run Code Online (Sandbox Code Playgroud)
由于使用静态常量的方法是不好的做法,并且因为我想改进代码,所以我希望使用Enums来实现相同的目标.有一些要求,其中之一是需要将状态作为数字类型保存到数据库中.因此需要将枚举常量转换为数值.以下是我的第一种方法,我想知道这是否是正确的方法呢?
class DocumentStatus{
public enum StatusFlag {
DOCUMENT_STATUS_NOT_DEFINED(1<<0),
DOCUMENT_STATUS_OK(1<<1),
DOCUMENT_STATUS_MISSING_TID_DIR(1<<2),
DOCUMENT_STATUS_MISSING_TIF_FILE(1<<3),
DOCUMENT_STATUS_MISSING_PDF_FILE(1<<4),
DOCUMENT_STATUS_MISSING_OCR_FILE(1<<5),
DOCUMENT_STATUS_PAGE_COUNT_TIF(1<<6),
DOCUMENT_STATUS_PAGE_COUNT_PDF(1<<7),
DOCUMENT_STATUS_UNAVAILABLE(1<<8);
private final long statusFlagValue;
StatusFlag(long statusFlagValue) {
this.statusFlagValue = statusFlagValue;
}
public long getStatusFlagValue(){
return statusFlagValue;
}
}
/**
* Translates a numeric status code into a Set of StatusFlag enums
* @param numeric statusValue
* @return EnumSet representing a documents status
*/
public EnumSet<StatusFlag> getStatusFlags(long statusValue) {
EnumSet statusFlags = EnumSet.noneOf(StatusFlag.class);
StatusFlag.each { statusFlag ->
long flagValue = statusFlag.statusFlagValue
if ( (flagValue&statusValue ) == flagValue ) {
statusFlags.add(statusFlag);
}
}
return statusFlags;
}
/**
* Translates a set of StatusFlag enums into a numeric status code
* @param Set if statusFlags
* @return numeric representation of the document status
*/
public long getStatusValue(Set<StatusFlag> flags) {
long value=0;
flags.each { statusFlag ->
value|=statusFlag.getStatusFlagValue()
}
return value;
}
public static void main(String[] args) {
DocumentStatus ds = new DocumentStatus();
Set statusFlags = EnumSet.of(
StatusFlag.DOCUMENT_STATUS_OK,
StatusFlag.DOCUMENT_STATUS_UNAVAILABLE);
assert ds.getStatusValue( statusFlags )==258 // 0000.0001|0000.0010
long numericStatusCode = 56;
statusFlags = ds.getStatusFlags(numericStatusCode);
assert !statusFlags.contains(StatusFlag.DOCUMENT_STATUS_OK);
assert statusFlags.contains(StatusFlag.DOCUMENT_STATUS_MISSING_TIF_FILE);
assert statusFlags.contains(StatusFlag.DOCUMENT_STATUS_MISSING_PDF_FILE);
assert statusFlags.contains(StatusFlag.DOCUMENT_STATUS_MISSING_OCR_FILE);
}
}
Run Code Online (Sandbox Code Playgroud)
Paŭ*_*ann 32
您可以简单地使用内部ordinal()值来计算它,而不是定义构造函数参数.
public enum StatusFlag {
DOCUMENT_STATUS_NOT_DEFINED,
DOCUMENT_STATUS_OK,
DOCUMENT_STATUS_MISSING_TID_DIR,
DOCUMENT_STATUS_MISSING_TIF_FILE,
DOCUMENT_STATUS_MISSING_PDF_FILE,
DOCUMENT_STATUS_MISSING_OCR_FILE,
DOCUMENT_STATUS_PAGE_COUNT_TIF,
DOCUMENT_STATUS_PAGE_COUNT_PDF,
DOCUMENT_STATUS_UNAVAILABLE;
public long getStatusFlagValue(){
return 1 << this.ordinal();
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,现在您应该放弃重新排序,插入(除了最后)或删除条目,否则标志值将会改变,并且数据库内容的含义将会改变.
Ray*_*yek 14
你的方法正是这样做的方法.
稍微好一点的方法是1 << this.ordinal()在构造枚举值时将结果存储在字段中.这样,您不必手动提供每个值,并且该标志仅计算一次.
public enum StatusFlag {
DOCUMENT_STATUS_NOT_DEFINED,
DOCUMENT_STATUS_OK,
DOCUMENT_STATUS_MISSING_TID_DIR,
DOCUMENT_STATUS_MISSING_TIF_FILE,
DOCUMENT_STATUS_MISSING_PDF_FILE,
DOCUMENT_STATUS_MISSING_OCR_FILE,
DOCUMENT_STATUS_PAGE_COUNT_TIF,
DOCUMENT_STATUS_PAGE_COUNT_PDF,
DOCUMENT_STATUS_UNAVAILABLE;
public final int flag;
StatusFlag() {
this.flag = 1 << this.ordinal();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:拥有isFlagSet方法也很有用.
不要给你的枚举值.使用an EnumSet来组合它们,并Enum.ordinal()在持久化时使用以转换为/从单个整数转换.Class.getEnumConstants()从整数重构集合时,您可能会发现有用.
我为这个问题制作了一个完整的库: http ://claude-martin.ch/enumbitset/
主要目标是在位字段中存储枚举类型集。但它也支持其他类型。
有了这个,您将不需要任何额外的方法,例如“getStatusFlags()”。只需添加接口EnumBitSetHelper(它像“特征”一样使用)即可在任何现有枚举类型上使用。每个枚举常量都可以创建一个“EnumBitSet”,它具有 Java 的 EnumSet 和 BitSet 的所有方法。然后,您可以使用这些枚举常量集并将它们转换为位字段值。
它支持多种格式,例如 BigInteger 和 long,可以轻松地将值存储到位字段中。但请注意,这仅适用于 Java 版本 8 及更高版本。
| 归档时间: |
|
| 查看次数: |
31330 次 |
| 最近记录: |