利用 位 来存储和传递 标记(true/false, 0/1) 的值

博文目录

文章目录


原理

假设有8个标记(配置项,值都是true/false)

标记定义为指数增长(2^n, n从0开始)数列, 有新的标记继续按规律往后面加就可以了

这种数列转换为二进制后有一个特性, 每个数都和二进制里的唯一一位相对应

索引标记二进制
110000-0000-0000-0001
220000-0000-0000-0010
340000-0000-0000-0100
480000-0000-0000-1000
5160000-0000-0001-0000
6320000-0000-0010-0000
7640000-0000-0100-0000
81280000-0000-1000-0000
92560000-0001-0000-0000

不同索引处的数相加的结果(每个数只能使用1次), 转换为二进制, 从右往左对应索引处为1, 其他位为0

用该二进制 与操作(&,都1为1否则0) 数列中的每一个数, 如果结果不为0, 即表示该数有被相加过, 即该位被标记过

如果用 long 来计算的话, 8byte, 64bit, 即 long 可以代表64个标记位, 一般足够使用了, 如果真不够, 那就再来个 long(可能会涉及到高低位啥的内容)

package com.mrathena;

public class Mrathena {

	public static void main(String[] args) {

		// 假设有8个标记(配置项,值都是true/false), 前后端可以通过8个参数来传递这些标记的情况, 但也有一种通过1个参数直接传所有标记的方法, 如下

		// 标记定义为指数增长(2^n, n从0开始), 有新的标记继续按规律往后面加就可以了
		// 这种数列转换为2进制后有一个特性, 每个数都和二进制里的唯一一位相对应, 如 1-0001, 2-0010, 4-0100, 8-1000, 16-00010000, 32-00100000, 64-01000000, 128-10000000, ....
		// 不同的数(每个数只能使用1次)相加的结果, 转换为二进制, 正好是涉及到的数的对应位为1其他位为0的二进制
		// 用该二进制 与操作(都1为1否则0) 数列中的每一个数, 如果结果不为0, 即表示该数有被相加过, 即该位被标记过
		// 如果用 long 来计算的话, 8byte, 64bit, 即 long 可以代表64个标记位, 一般足够使用了, 如果真不够, 那就再来个 long(可能会涉及到高低位啥的内容)
		// 看下面的例子

		int	flag1 = 1;
		int flag2 = 2;
		int flag3 = 4;
		int flag4 = 8;
		int flag5 = 16;
		int flag6 = 32;
		int flag7 = 64;
		int flag8 = 128;

		int flag = flag1 + flag3; // 0000 0101, 正好是从右往左的第一位和第三位是1, 其他位是0
		print(flag);
		// 5 & 1 -> 0000 0101 & 0000 0001 -> 0000 0001 != 0
		// 5 & 2 -> 0000 0101 & 0000 0010 -> 0000 0000 == 0
		// 5 & 4 -> 0000 0101 & 0000 0100 -> 0000 0100 != 0
		// 5 & 8 -> 0000 0101 & 0000 1000 -> 0000 0000 == 0

		flag = flag8; // 1000 0000, 正好是从右往左的第八位是1, 其他位是0
		print(flag);

		flag = flag2 + flag4 + flag6 + flag8; // 1010 1010, 正好是从右往左的2468位是1, 其他位是0
		print(flag);
		
		flag = flag4 + flag5 + flag6 + flag7 + flag8; // 1111 1000, 正好是从右往左的45678位是1, 其他位是0
		print(flag);

	}

	private static void print(int flag) {
		int	flag1 = 1;
		int flag2 = 2;
		int flag3 = 4;
		int flag4 = 8;
		int flag5 = 16;
		int flag6 = 32;
		int flag7 = 64;
		int flag8 = 128;
		System.out.println((flag & flag1) != 0);
		System.out.println((flag & flag2) != 0);
		System.out.println((flag & flag3) != 0);
		System.out.println((flag & flag4) != 0);
		System.out.println((flag & flag5) != 0);
		System.out.println((flag & flag6) != 0);
		System.out.println((flag & flag7) != 0);
		System.out.println((flag & flag8) != 0);
		System.out.println();
	}

}
true
false
true
false
false
false
false
false

false
false
false
false
false
false
false
true

false
true
false
true
false
true
false
true

false
false
false
true
true
true
true
true

场景

前后端传值, 当有大量开关时, 前端只需传一个 相加的和, 后端通过分析就可知道前端都选了哪几项, 清晰明了, 无需传大量的字段

数据库把多个开关合并到一个字段中, 节约空间, 但是不利于维护与沟通

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值