Как представить 4 булевы возможности в одном значении - PullRequest
15 голосов
/ 12 марта 2011

Я хочу хранить 4 логических значения в одном значении.Например, я хочу одно значение, которое говорит, является ли человек:

IsSingle<br> IsGraduate<br> IsMale<br> IsLookingForPartner

Так хорошо ли хранить их в байте, чьи 4 бита могут быть выделены, один длякаждый параметр.Если бит установлен в 1, тогда этот логический параметр имеет значение true.Поэтому я могу выполнять операции сдвига битов, чтобы найти то, что все верно.если значение байта равно 111, то первые три параметра имеют значение true.Это хороший способ?Есть ли лучший способ реализовать это?

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

Ответы [ 8 ]

17 голосов
/ 12 марта 2011

Битовые флаги.

public static final int IsSingle = 1 << 0;
public static final int IsGraduate = 1 << 1;
public static final int IsMale = 1 << 2;
public static final int IsLookingForPartner = 1 << 3;

...

if ((Value & IsSingle) != 0) {
}

if ((Value & IsGraduate) != 0) {
}

// Set "Single"
Value |= IsSingle;

// Remove "Graduate"
Value &= ~IsGraduate;
11 голосов
/ 12 марта 2011

Это действительно возможно, но это не рекомендуется.

Что, если вы хотите найти в своей базе данных всех одиноких студентов? Или мужской? Несмотря на то, что место, которое вы экономите, минимально, вы отказываетесь от возможности индексировать ваши данные не только для более быстрого поиска, но и для поиска любых данных, которые имеют критерии запроса в зависимости от любого из этих атрибутов, вам потребуется выполнить операции сдвига битов. на всех записях (или проверке по нескольким целочисленным значениям), которые в конечном итоге будут ужасно медленными.

По моему скромному мнению, дополнительная сложность не очень полезна: базы данных могут обрабатывать 4 отдельных поля, и для этого есть веские причины (например, легко запрашивать данные в этих полях).

10 голосов
/ 12 марта 2011

Вы можете обнаружить, что EnumSet является естественным способом представления этой информации.EnumSet использует битовую маску под капотом.

enum Interest {
   IsSingle,
   IsGraduate,
   IsMale,
   IsLookingForPartner 
}

EnumSet<Interest> interests = EnumSet.of(Interest.IsSingle, Interest.IsMale);

Вы можете добавить любое количество значений перечисления.

8 голосов
/ 12 марта 2011

Используйте бинарную упаковку.Определите для них константы как:

IsSingle = 1;
IsGraduate = 2;
IsMale = 4;
IsLookingForPartner = 8;

И объедините их с логической операцией ИЛИ.Таким образом, каждая возможность будет представлена ​​битом в двоичном представлении числа. Вы можете проверить, используя И упакованное значение с любой из констант:

short status = IsSingle | IsMale;    // will give 5

if ((status & IsMale) != 0)
    System.out.println("Male.");
3 голосов
/ 12 марта 2011

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

  1. Remove isLookingForPartner // избыточный бит будет всегда - порядок имеет значение
  2. Добавление новых параметров
  3. Найтивсе люди, которые isLookingForPartner == true // будут медленными
3 голосов
/ 12 марта 2011

Рассматривали ли вы использовать байт для хранения значений? Затем вы можете сделать что-то вроде следующего:

public Byte setDetails(bool isSingle, bool isGraduate, bool isMale, bool isLooking)
{
    Byte result = 0;

    //Set the details
    if (isSingle) result = result | 1;
    if (isGraduate) result = result | 2;
    if (isMale) result = result | 4;
    if (isLooking) result = result | 8;

    return result;
}

Тогда позже вы можете использовать код как:

Byte details = getDetails(true, false, true, false);
bool isSingle = (details & 1) != 0;

чтобы получить детали.

... Тем не менее, ради трех байтов, стоит ли вся эта дополнительная работа и константы?

3 голосов
/ 12 марта 2011

Лучше всего будет boolean[4], где вы сохраните каждое значение в другой ячейке массива, и это займет минимум места!

напишите этот фрагмент кода в своем классе:

private boolean[] values = new boolean[4];

void setValue(String name, boolean value){
    if(name=="IsSingle")
        values[0] = value;
    else if(name=="IsGraduate")
        values[1] = value;
    else if(name=="IsMale")
        values[2] = value;
    else if(name=="IsLookingForPartner")
        values[3] = value;
}

boolean getValue(String name){
    if(name=="IsSingle")
        return values[0];
    else if(name=="IsGraduate")
        return values[1];
    else if(name=="IsMale")
        return values[2];
    else if(name=="IsLookingForPartner")
        return values[3];
    else
        return false;
}

теперь просто используйте это как: setValue("IsGraduate", true); getValue("IsMale");

0 голосов
/ 12 марта 2011

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

...