在我们制作的应用程序(iOS / Swift,Android)中,我们有一个用户希望接收推送通知的设置页面。其中一个设置是供用户选择一周中的哪几天。
我的问题是关于如何将此选项存储为一个变量,而不是七个布尔值。该设置将被发送到服务器/数据库进行存储,我想我们可以简单地在数据库中使用单个字节字段。
而不是monday=true, tuesday=false, ...
,我想使用例如'10001010',其中1为真,0为假,这将转换为monday=true(1), tuesday=false(0), etc
(给定星期一是一周的第一天,它是。 )。
这是存储此类数据的有效方法吗?我可以创建这样的字节吗?或者使用字符串/ char []“10001010”是一种更常用的做法?或者数据库(例如MySQL)可以将bool [](10001010)存储为一个字段吗?还是有另一种更好的做法吗? 用于权限的方法也浮现在脑海中(你知道,777,只是简化了)
当然,某些变体需要服务器对变量使用相同的逻辑,但在这种情况下这没有问题。
简短的解释,我需要7个布尔值,一周中的每一天,并且我想比每天一个变量更有效地存储它。有最佳实践吗?
答案 0 :(得分:4)
这个问题“破坏”过早优化:
7个布尔变量占用的空间可以忽略不计(可能是7 x 4个字节)...除非您需要同时在内存中保存数十万个用户设置对象。
除非您发送数百万条消息,否则网络带宽的差异可以忽略不计。
数据库表空间的差异可以忽略不计......除非您在数据库中存储了数百万条用户记录。
这是存储此类数据的有效方法吗?
定义“有效”。但是,它(大多数情况下)都有效。
我想比每天一个变量更有效地存储它
是的......但是有必要这样做吗?你有没有量化这个(假定的)效率可以获得多少。
对于它的价值,将多个布尔值打包成一个字节/字/任何东西都有一些惩罚。其中包括:
访问和更新打包到单个变量中的标志涉及额外的按位操作,这往往会使事情变慢。
将标志表示为数据库中的位将使SQL查询更加困难,具体取决于数据库。 (见http://blog.jooq.org/2011/10/30/the-comprehensive-sql-bitwise-operations-compatibility-list/)。它也可能会干扰查询优化。
可读性。
答案 1 :(得分: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 ;
}
}
这当然只是一些快速而肮脏的示例代码,但我希望,它使概念清晰。
答案 2 :(得分: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 enum中添加一个现成的值作为字段,而不是使用1&lt;
答案 3 :(得分:0)
考虑使用Joshua Bloch的“Effective Java”中第32项建议的EnumSet。 (EnumSets是内部BitVectors)
使用java.time.DayOfWeek
作为枚举类型。
Set中包含的星期几是您的用户选择的星期几。其他人没有被选中。
EnumSet<DayOfWeek> selectedDays = EnumSet.of(DayOfWeek.MONDAY, DayOfWeek.FRIDAY);
selectedDays.contains(DayOfWeek.MONDAY); // true
selectedDays.contains(DayOfWeek.TUESDAY); // false