2015-11-05 2 views
0

Я работаю над веб-приложением Java и в таблице базы данных у меня есть столбец типа номера. но этот столбец предназначен для хранения нескольких значений. (т.е. Разрешение, как указано ниже)Java Bitwise & operator multiple permission

  1. nothing = 1;
  2. вид = 2;
  3. add = 4;
  4. Редактировать = 8;
  5. insert = 16;
  6. delete = 32;
  7. all = 64;

Проблема

  1. если столбец имеет значение 3 -> то мне нужно, чтобы забрать ничего, просматривать, как разрешения.
  2. если этот столбец имеет значение 12 ->, тогда мне нужно выбрать add, .

что-то вроде этого

Я undserstood, как мы можем сделать это с помощью оператора побитового. Любой код для этого будет отличным.

+1

Почему «ничего» не имеет значения? Почему бы просто не принять 0 как «никаких разрешений»? Кроме того, вы можете использовать перечисление вместо этого и полагаться на ординалы, хотя {de,} сериализация его {from, to} базы данных может быть проблемой. И почему «все» отличная ценность? – fge

+0

Любая проблема с использованием оператора равенства? 'value == 3' –

+3

Я бы подумал об использовании BitSet (http://docs.oracle.com/javase/7/docs/api/java/util/BitSet.html) и просто вызвал' get() 'to проверьте, установлен ли бит. – Nim

ответ

0

Спасибо за все в ответе. Я создал простую утилиту с bitand оператора, который работает отлично подходит для выше USECASE

Проблема:

1) getPermission (3) не будет возвращать ничего и зрения.

public static ArrayList<Integer> getPermission(int day) { 
    List<Integer> places = Arrays.asList(1, 2, 4, 8, 16, 32, 64); 
    ArrayList<Integer> d = new ArrayList<Integer>(); 
    for (Integer i : places) { 
     if (bitWiseAnd(day, i)) { 
      d.add(i); 
     } 
    } 
    return d; 
} 

public static boolean bitWiseAnd(int bitwise, int operator) { 
    return (bitwise & operator) > 0; 
} 
3

Прежде всего, ваш набор разрешений действительно странный; «ничего» и «все» являются разделяемыми значениями, мм.

Ну, вы можете использовать перечисление и полагаться на ординалы; это своего рода хакерский, но он может работать. Пример код:

public enum Permission 
{ 
    NOTHING, 
    VIEW, 
    ADD, 
    EDIT, 
    INSERT, 
    DELETE, 
    ALL, 
    ; 

    private static final Set<Permission> ALL_PERMISSIONS; 

    static { 
     final Set<Permission> set = values(); 
     set.remove(NOTHING); 
     set.remove(ALL); 
     ALL_PERMISSIONS = Collections.unmodifiableSet(set); 
    } 

    private static final int NOTHING_ORDINAL = NOTHING.ordinal(); 
    private static final int ALL_ORDINAL = ALL.ordinal(); 

    public static Set<Permission> fromInt(final int value) 
    { 
     int mask; 

     mask = 1 << NOTHING_ORDINAL; 
     if (value & mask == mask) 
      return Collections.emptySet(); 

     mask = 1 << ALL_ORDINAL; 
     if (value & mask == mask) 
      return ALL_PERMISSIONS; 

     final Set<Permission> set = EnumSet.noneOf(Permission.class); 

     for (final Permission p: ALL_PERMISSIONS) { 
      mask = 1 << p.ordinal(); 
      if (value & mask == mask) 
       set.add(p); 
     } 

     return Collections.unmodifiableSet(set); 
    } 
} 

Теперь, почему эта работа: это потому, что .ordinal() из Enum значения является показателем появления в перечислении. Здесь NOTHING имеет порядковый номер 0 и ALL имеет порядковый номер 6. Поэтому, если вы должны были сопоставить int с набором разрешений, вам нужно будет проверить, что для любого разрешения p установлен p-й бит в целочисленном размере. Что, в свою очередь, означает, что i & (1 << p.ordinal()) == 1 << p.ordinal().

Для получения дополнительной информации см. Javadoc Enum.


ДИЗАЙН РАССМОТРЕНИЕ: Не хранить «ничего» и «все» в качестве возможных значений. Оба они могут быть сопоставлены с целыми числами:

  • 0 для каких-либо разрешений:
  • всех значений для просмотра, добавление и т.д. для всех разрешений (в основном, так как здесь у вас есть 5 разрешений в целом, то значение будет (1 < < 5) - 1).
+0

Эта логика зависит от того, что порядковое значение перечисления является одним и тем же на всю вечность, иначе алгоритм сломается. – specializt

+0

@specializt и это так. Прочтите документацию «EnumSet». – fge

+0

@fge получает некоторую ошибку в вашем коде, если (значение & маска) set.add (p); и if (value & mask == mask), если (value & mask == mask). я использую java 1.6 – user3595995

3

Я думаю, вы имеете в виду побитовые операции и бинарные литералы.

В вашем случае, вы должны использовать битовую маску (исправленную версию, спасибо @Paul Боддингтон & @Jaroslaw Павлака):

final int MASK_NOTHING = 1; 
final int MASK_VIEW = 0b10; 
final int MASK_ADD = 0b100; 
final int MASK_EDIT = 0b1000; 
final int MASK_INSERT = 0b10000; 
final int MASK_DELETE = 0b100000; 
final int MASK_ALL = 0b1000000; 
int column = 0; //YOUR DATA HERE 

if((column & MASK_NOTHING) > 0) 
{ 

} 

if((column & MASK_VIEW) > 0) 
{ 

} 

заметь: все возможные bitflags могут быть установлены независимо друг от друга. .. так как предотвратить установление более чем по одному или обрабатывать все из этих случаев

Двоичные литералы: https://docs.oracle.com/javase/7/docs/technotes/guides/language/binary-literals.html Операторы: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

+0

Это правильный путь, за исключением того, что OP должен использовать 0 как ничего, а '&' вместе все возможные разрешения использовать как 'MASK_ALL' вместо использования жесткого кодированного значения. Довольно стандартный материал на самом деле фактически сделал исследование. –

+0

ну нет «правильного» способа пойти ... но это один из самых быстрых алгоритмов для этой работы - по причинам удобства использования люди могли выбрать другой ответ – specializt

+0

@JoshTriiJohnston да, но '|' – harold