03 MyBitSet
来源:互联网 发布:javascript官方文档 编辑:程序博客网 时间:2024/06/04 18:08
前言
这是一个之前的时候, 没事想模拟BitSet实现, 当时 记得是为了素数问题吧, 或者是其他的问题, 或者是无聊想起了, 这个只实现了BitSet的存取, 可以当做一个小例子没事的时候看看
就是涉及一些位操作, 移位操作
算法 和java.util.BitSet基本上是一致的, 不过这里的存储是使用int[] 来存放数据的
参考代码
/** * file name : Test18MyBitSet.java * created at : 8:15:46 PM May 23, 2015 * created by 970655147 */package com.hx.test03;public class Test19MyBitSet { // BitSet的模拟 public static void main(String []args) {// int size = 65;// size = (size + 32 - 1) >> 5;// Log.log(size);// Log.log(Integer.toBinaryString(BitSet.HEAD_ONE_MASK));// BitSet bs = new BitSet();// Log.log(bs.toString());// bs.set(3, true);// Log.log(bs.toString());// bs.set(32, true);// Log.log(bs.toString());// // Log.log(bs.get(2));// Log.log(bs.get(3));// Log.log(bs.get(32));// Log.log(bs.get(33));// Log.log(bs.get(1, 10));// // int start = 3, end = 42;// bs.set(start, end, true);// Log.log(bs.get(start - 1, end + 1));// BitSet bs = new BitSet(128);// int start = 1, end = 74;// bs.set(start, end, true);// Log.log(bs.get(start - 1, end + 1)); } // 一个模拟BitSet的类 static class BitSet { // 默认的大小, int的位数, 获取int索引的mask, 获取int偏移的mask // 0x00000000000000000000000000000001 // 0x11111111111111111111111111111111 // 0x10000000000000000000000000000000 private static int DEFAULT_SIZE = 64; private static int INT_SIZE = 32; private static int INT_RIGHT_SHIFT_SIZE = 5; private static int INT_MASK = INT_SIZE - 1; private static int ONE_MASK = 1; private static int ALL_ONE_MASK = -1; private static int HEAD_ONE_MASK = ONE_MASK << (INT_SIZE-1); // 存放数据的int[], 以及容量 private int[] data; private int capacity; private int size; // 初始化 public BitSet() { this(DEFAULT_SIZE); } public BitSet(int capacity) { int num = (capacity + INT_MASK) >> INT_RIGHT_SHIFT_SIZE; data = new int[num]; this.capacity = capacity; size = 0; } // 获取idx处的值 public boolean get(int idx) { checkForIdx(idx); int theKInt = intIdx(idx); int theKBit = bitIdx(idx); return get0(theKInt, theKBit); } // 获取start到end的值 public boolean[] get(int start, int end) { checkForIdx(start); checkForIdx(end); int len = end - start; checkForLen(len); boolean[] res = new boolean[len]; int idx = 0; for(int i=start; i<end; i++) { int theKInt = intIdx(i); int theKBit = bitIdx(i); res[idx ++] = get0(theKInt, theKBit); } return res; } // 设置idx处的值 public void set(int idx, boolean val) { checkForIdx(idx); int theKInt = intIdx(idx); int theKBit = bitIdx(idx); set0(theKInt, theKBit, val); if(val && (idx > size) ) { size = idx; } } // 获取start到end的值 // 如果start和end实在同一个int上面 设置start和end之间的值 // 否则先设置start之后的值, 在设置end之前的值 在设置其间的所有int public void set(int start, int end, boolean val) { checkForIdx(start); checkForIdx(end); int len = end - start; checkForLen(len); int theKInt01 = intIdx(start); int theKBit01 = bitIdx(start); int theKInt02 = intIdx(end); int theKBit02 = bitIdx(end); if(theKInt01 == theKInt02) { int mask = ALL_ONE_MASK; mask >>>= theKBit01; mask <<= (theKBit01 + (INT_SIZE - theKBit02)); mask >>>= (INT_SIZE - theKBit02); if(val) { data[theKInt01] |= mask; } else { data[theKInt01] &= (~mask); } } else { int startMask = ALL_ONE_MASK >>> theKBit01; int endMask = ALL_ONE_MASK << (INT_SIZE - theKBit02); startMask <<= theKBit01; endMask >>>= (INT_SIZE - theKBit02);// Log.log(Integer.toBinaryString(startMask));// Log.log(Integer.toBinaryString(endMask)); if(val) { data[theKInt01] |= startMask; data[theKInt02] |= endMask; for(int i=theKInt01+1; i<theKInt02; i++) { data[i] |= ALL_ONE_MASK; } } else { data[theKInt01] &= (~startMask); data[theKInt02] &= (~endMask); for(int i=theKInt01+1; i<theKInt02; i++) { data[i] &= (~ALL_ONE_MASK); } } } if(val && (end > size) ) { size = end; } } // assistMethod private boolean get0(int theKInt, int theKBit) { return ( ((data[theKInt] >>> theKBit ) & ONE_MASK ) == 1 ); } // assistMethod private void set0(int theKInt, int theKBit, boolean val) { if(val) { data[theKInt] |= (ONE_MASK << theKBit); } else { data[theKInt] &= (~(ONE_MASK << theKBit)); } } // 获取 private int intIdx(int idx) { return idx >>> INT_RIGHT_SHIFT_SIZE; } private int bitIdx(int idx) { return idx & INT_MASK; } // 校验索引 private void checkForIdx(int idx) { if(idx < 0 || idx >= capacity) { throw new RuntimeException("check index exception..."); } } // 校验长度 private void checkForLen(int len) { if(len <= 0) { throw new RuntimeException("check index exception, endIndex must bigger than startIndex..."); } } // 当前BitSet的字符串表示 public String toString() { // 1 0 ... 包含空格 预留data.length * 20个空间 StringBuilder sb = new StringBuilder((data.length << INT_RIGHT_SHIFT_SIZE) * 4); int mask = ONE_MASK; sb.append("low -> high \r\n"); for(int i=0; i<data.length; i++) { int tmp = data[i]; for(int j=0; j<INT_SIZE; j++) { sb.append((tmp & mask) + " "); tmp >>>= 1; } sb.append("\r\n"); } return sb.toString(); } }}
效果截图
0 0
- 03 MyBitSet
- 03
- 03
- 03
- 03
- 03
- 03
- 2010-03-03
- 2010-03-03
- 10-03-03 培训
- Python 2011-03-03
- 2010-03-03
- 2011-03-03 LDAP
- 2013-03-03
- 2014/03/03
- 2015-03-03
- 2016-03-03补写
- 2017-03-03
- Dell PowerEdge R710配置raid磁盘阵列
- shell 和 环境变量
- EasyUI - 自定义页面等待插件
- ubuntu android studio Error:Execution failed for task ':app:validateDebugSigning'.
- Ubuntu挂载新硬盘
- 03 MyBitSet
- Eclipse调用hadoop2运行MR程序
- 一个关于Json数据List和对象嵌套反序列化的工具类,java(20151130)
- CSS基础学习十七:CSS布局之定位
- 使用nineoldandroids仿制QQ侧滑菜单
- Scrum Master 面试题 – 你必须知道的22个Scrum基础知识
- HDFS利用QJM实现HA(HDFS High Availability Using the Quorum Journal Manager)
- 备用DNS域名服务器
- 树状数组求逆序数