用一个int值实现多选(二进制、效率)

今天仔细了解了下温少的fastjson源码,发现真的是当之无愧的java中最快的json解析库!也发现了一种有趣的算法(当然fastjson中还有TheadLocal缓存、对象路径化、解决互相引用死循环等值得我们深入学习),在fastjson中应用场景是配置序列化json和解析json的可变配置中,他只用了两个int变量来配置(通常我会用List或者Map),先看我模仿他的实现代码先(最后会简要说明),我应用的场景是:高中考试的多选题



实现枚举

package here.wait.go.test.choosed;

/**
 * 多选枚举
 * 
 * @author Wait
 * @date 2013年12月20日 
 * @time 下午10:40:22
 * @email here.wait.go@gmail.com
 * @version 1.0
 */
public enum MultipleChoiceEnum
{
	A, B, C, D;
	private final int mask;
	private  MultipleChoiceEnum()
	{
		mask = 1<<ordinal();
	}
	
	public final int getMask()
	{
		return mask;
	}
	
	/**
	 * 判断是否已经选择
	 * 
	 * @param multipleChoices
	 * @param multipleChoiceEnum
	 * @return
	 */
	public static boolean isChoosed(int multipleChoices, MultipleChoiceEnum multipleChoiceEnum)
	{
		return 0 != (multipleChoices & multipleChoiceEnum.getMask());
	}
}


测试类

package here.wait.go.test.choosed;

import org.junit.Assert;
import org.junit.Test;

/**
 * 模拟多选情况
 * 
 * 选择了A
 * multipleChoice |= MultipleChoiceEnum.A.getMask();
 * 
 * 取消选择A
 * multipleChoice &= ~MultipleChoiceEnum.A.getMask();
 * 
 * @author Wait
 * @date 2013年12月20日 
 * @time 下午10:48:33
 * @email here.wait.go@gmail.com
 * @version 1.0
 */
public class MultipleChoiceTest
{
	@Test
	public void test()
	{
		int multipleChoices = 0;
		//选择了A
		multipleChoices |= MultipleChoiceEnum.A.getMask();
		//选择了B
		multipleChoices |= MultipleChoiceEnum.B.getMask();
		//选择C
		multipleChoices |= MultipleChoiceEnum.C.getMask();
		//突然看同桌不爽,把已选的C去掉
		multipleChoices &= ~MultipleChoiceEnum.C.getMask();
		
		
		Assert.assertEquals(true, MultipleChoiceEnum.isChoosed(multipleChoices, MultipleChoiceEnum.A));
		Assert.assertEquals(true, MultipleChoiceEnum.isChoosed(multipleChoices, MultipleChoiceEnum.B));
		Assert.assertEquals(false, MultipleChoiceEnum.isChoosed(multipleChoices, MultipleChoiceEnum.C));
		Assert.assertEquals(false, MultipleChoiceEnum.isChoosed(multipleChoices, MultipleChoiceEnum.D));
	}
	
}

说明

如上场景有A、B、C、D四个选项

调用方法                    式子                  二进制

A.getMark()              1<<0                       1

B.getMark()              1<<1                     10

C.getMark()              1<<2                    100

D.getMark()              1<<3                   1000

选上是用运算符|((有1就1)运算规则:参与运算的二进制数字,低位对齐,高位不足的补零,对应的二进制位有一个为1则结果为1,否则为0。

全部选上是1111,所以每个选项占一位

去掉选项是&=~( &位与运算符(都1才1)运算规则:参与运算的二进制数字,低位对齐,高位不足的补零,对应的二进制位,都是1的为1,否则为0。

例如去掉B选项:1111&=~10->1111&=1101->1101

最后怎么知道那个选项被选上了,考试要改试卷了!

正确答案是A、C、D

程序怎么判断呢?是这样的

1101&1(A) !=0 ->  true

1101&100(C)!=0 -> true

1101&1000(D)!=0 -> true

恭喜全对了!


优越性

1、比List或者Array的穷举效率要高

2、比使用Map的查表方式更省内存空间

局限性

1、因为是使用二进制的,所以int类型最多只能有32个选项;

2、代码可读性低

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值