我可以为布尔数组使用“byte”吗?

4
在我们正在开发的应用程序中(iOS/Swift,Android),我们有一个设置页面,用户可以在其中选择哪些天接收推送通知。其中之一的设置是让用户选择每周的哪几天。
我的问题是如何将此选项存储为一个变量,而不是七个布尔值。这个设置将被发送到服务器/数据库进行存储,我想我们可以在数据库中使用单个字节字段。
我想使用“10001010”这样的二进制数来表示这个选项,其中1表示选中,0表示未选中,例如“monday=true(1),tuesday=false(0)”(假设星期一是一周的第一天)。
这种方式是否可行?我能否创建这样的字节?或者更常见的做法是使用字符串/char[] "10001010"吗?或者数据库(例如MySQL)是否可以将bool[](10001010)存储为一个字段?还是有其他更好的做法?
当然,某些变化需要服务器使用相同的逻辑来处理变量,但在这种情况下并没有问题。
简单地说,我需要七个布尔值,分别代表每周的七天,并且希望以比每天一个变量更高效的方式存储它。是否有最佳实践?

6
考虑一个 BitSet。 - Alex Salauyou
从内存角度来看,使用一个字节或位集来表示7个布尔值可能是最好的选择;从维护角度来看,我可能会使用一些更易于阅读的东西,例如像1010000x-x----这样的字符串。如果数据库列不需要支持更多的基本CRUD功能(例如在这些列上没有排序、没有连接等),您也可以将设置保存为JSON字符串等。 - Thomas
1
“有没有‘最佳实践’?”- 是的。最佳实践是要自己了解利弊,并将这些知识应用于问题中。最佳实践是不要问是否有“最佳实践”! - Stephen C
4个回答

4
这个问题太过于着急优化:
  • 7个布尔变量占用的空间是微不足道的(可能是7 x 4字节)......除非您需要在内存中同时保存数十万个用户设置对象。

  • 网络带宽的差异微不足道......除非您发送了数百万条消息。

  • 数据库表空间的差异微不足道......除非您在数据库中存储数百万个用户记录。


这是一种有效存储此类数据的方式吗?

“有效”如何定义?但是大致可行。

我想比每天一个变量更有效地存储它

是的......但这是必要的吗?您有没有量化到这种(假定)效率可以获得多少收益?


值得一提的是,将多个布尔值打包到一个字节/单词/其他中会带来许多罚款。这些包括:


这里的其他答案给了我我所要求的,但你给了我更多!你关于SQL查询惩罚的注释是我没有想到过的,听起来非常正确。将会有选择字段的查询,例如where monday=true,当单独处理数十万行的查询时,我同意这可能会导致严重的惩罚。这对我来说是正确的答案。然而,对于其他仍然有效的用户,我建议看看其他答案。 - Sti

1
你可以像这样存储它。
class A {
    public static final int MONDAY = 0;
    ...
    public static final int SUNDAY = 6;

    // call with the above defined constants for day
    public byte addDay(byte b, int day) {
        return (byte) (b | (1 << day));
    }

    public boolean isDaySet(byte b, int day) {
        return ((b >> day) & 1) == 1 ;
    }
}

当然,这只是一些快速而简单的示例代码,但我希望它能让概念更加清晰。


感谢您的编辑。我忘记从我的IDE中复制它了;). - RafToTheK

1

只需对字节执行一些位运算。示例代码

enum Days {
    MON,
    TUE,
    WED,
    THU,
    FRI,
    SAT,
    SUN
}

public static void main(String[] args) {

    byte encode = (byte)0b1010000;

    for ( Days d : Days.values() ) {
        boolean present = (encode & 1<<d.ordinal()) != 0;
        System.out.println(d + " " + present);
    }

    System.out.println("Adding MON, removing SUN");

    encode |= (1<<Days.MON.ordinal());
    encode &= ~(1<<Days.SUN.ordinal());

    for ( Days d : Days.values() ) {
        boolean present = (encode & 1<<d.ordinal()) != 0;
        System.out.println(d + " " + present);
    }

}

当然,你应该将其封装到一些更好的类/访问器方法中,可能直接将一个可用的值添加到Days枚举作为字段,而不是使用1<。

0

考虑使用 Joshua Bloch 的 "Effective Java" 中第32条建议中提到的 EnumSet。 (EnumSets 内部是位向量)

使用 java.time.DayOfWeek 作为枚举类型。

集合中包含的星期几是用户选择的那些。其他的则未被选择。

EnumSet<DayOfWeek> selectedDays = EnumSet.of(DayOfWeek.MONDAY, DayOfWeek.FRIDAY);

selectedDays.contains(DayOfWeek.MONDAY); // true
selectedDays.contains(DayOfWeek.TUESDAY); // false

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接