Java 正确使用位集替换基于int的标志。可能吗?
我从用作标志的数据源获取int。例如:Java 正确使用位集替换基于int的标志。可能吗?,java,performance,bit,bitset,Java,Performance,Bit,Bitset,我从用作标志的数据源获取int。例如: private static final int EMPLOYEE = 0x00000001; private static final int IT = 0x00000002; private static final int MARKETING = 0x00000004; private static final int DATA = 0x00000008; privat
private static final int EMPLOYEE = 0x00000001;
private static final int IT = 0x00000002;
private static final int MARKETING = 0x00000004;
private static final int DATA = 0x00000008;
private static final int DBAs = IT | DATA;
private static final int DATA_REPORTERS = MARKETING | DATA;
private static boolean isDba(int flag){
return (flag & DBAs) == flag;
}
private static boolean isInIT(int flag) {
return (flag & IT) == flag;
}
class Employee {
private int role;
private final String name;
//etc
}
employee = fetchEmployee()
if(isDba(employee.role)){
System.out.println("Is a DBA");
}
这似乎工作正常,但我也在研究EnumSet
,以防我可以稍微简化代码,但在我看来,它并没有这样做。例如,我需要:
private static final int EMPLOYEE = 1; // bit 1
private static final int IT = 2; // bit 2
private static final int MARKETING = 3; // bit 3
private static final int DATA = 4; // bit 4
哪些是要设置的单个位,但我可以找出如何执行以下操作:
private static final int DBAs = IT | DATA;
private static final int DATA_REPORTERS = MARKETING | DATA;
使用位集
那么如何使用
位集
(假设位集
是正确的选择,因为我不需要对位集进行任何更新,只需检查标志即可)我认为枚举集比位集更可取,尤其是当您只需要只读访问时
enum EmployeeRole {
EMPLOYEE, IT, MARKETING, DATA
}
EnumSet<EmployeeRole> DBAs = EnumSet.of(IT, DATA);
EnumSet<EmployeeRole> DATA_REPORTERS = EnumSet.of(MARKETING, DATA);
class Employee {
EnumSet<EmployeeRole> roles;
boolean isDba(){
for(EmployeeRole role: roles){
if(DBAs.contains(role){
return true;
}
}
return false;
}
}
或者您可以为此编写一个自定义的hibernate用户类型。这些可能会启发您:我认为使用位掩码就可以了。或者,创建一个包含4个布尔字段的类。为什么要使用
位集
?为什么要用性能来标记问题?@Sweeper:这意味着每种类型都有X个标志(我没有4个)。Jocke:因为我认为从性能角度看,我的方法应该比其他方法更好,但希望听到更多选项,那么为什么不测量它(我知道很难),或者编译并读取字节码。我喜欢你提供的代码片段。它很干净。我真的不确定性能方面是否更好,尤其是如果我需要依赖于库的话。我的用例是从网络源(即int或long over the wire)获取标志,拥有大量具有角色的此类对象,并将它们保存在本地数据库缓存中。似乎EnumSet
增加了额外的开销和额外的依赖性,因为我可以直接检查粘贴在帖子中的标志。你的想法是什么?可能是我遗漏了什么?所以如果我得到这个enumultils.processBitVector(EmployeeRole.class,rolesalong)
首先会如何生成它?我是说rolesalong
?它是特定于java的吗?转换过程中会有额外的开销,这是真的。然而,枚举集本身上的方法经过了充分优化,因此.contains()应该与您自己的位掩码一样快。如果性能是一个问题,并且转换开销会对此产生影响,我想我也会像您一样坚持使用位掩码方法。除了性能之外,这种方法是Java特有的吗?我的意思是,从网络源代码来看,如果他们没有EmployeeRole
的代码库,他们如何让rolesSlong
通过网络发送它?我猜EnumUtils使用普通的位屏蔽方法,所以rolesSlong不是特定于java的。它是64位的,因此允许设置64个不同的标志。我猜它使用了枚举的序数,所以在这个例子中,雇员是第一位,它是第二位,等等。你必须做一些测试来确定。
//write
long rolesAsLong = EnumUtils.generateBitVector(EmployeeRole.class, employee.getRoles())
//read
employee.setRoles(EnumUtils.processBitVector(EmployeeRole.class, rolesAsLong));