Правильное использование BitSet для замены флага на основе int. Является ли это возможным? - PullRequest
0 голосов
/ 27 марта 2020

Я получаю 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;  
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;  

с BitSet

Так как вышеперечисленное было бы правильно реализовано с BitSet (при условии, что BitSet - правильный выбор, так как мне не нужно делать никаких обновлений для набора битов, просто проверьте флаги)

1 Ответ

1 голос
/ 27 марта 2020

Я думаю, что EnumSet предпочтительнее BitSet, особенно если вам нужен только доступ readOnly.

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;
  }
}

Но если вы храните свои флаги в базе данных как одно поле в базе данных, вам нужно преобразование, например, с использованием старого доброго apache commons-lang EnumUtils

//write
long rolesAsLong = EnumUtils.generateBitVector(EmployeeRole.class, employee.getRoles())
//read
employee.setRoles(EnumUtils.processBitVector(EmployeeRole.class, rolesAsLong));

Или вы можете написать собственный спящий пользовательский тип для этого. Это может вдохновить вас: https://github.com/search?q=EnumSetUserType&type=Code

...