转载 http://qihigh-hotmail-com.iteye.com/blog/1329696
二进制的与、或、非运算特殊用法的不同运用场合:
1.权限控制下面我用几个数字来代表增,删,改,查。(注:1带有有权限,有几个1,就代表有几个权限,1的位置不同,所带表的权限也不同)
Java代码
- 1---------增--------(转二进制)-----(0001)
- 2---------删----------------------(0010)
- 4--------改----------------------(0100)
- 8--------查----------------------(1000)
管理员拥有所有的权限,所以,控制管理员的权限的数字为(15),转化二进制的格式为:(1111)。算法为:“1|2|4|8“
撤销管理员的删权限(2),控制管理员的权限的数字为(13),转化二进制的格式为:(1101)。算法为:”15 & (~2)”
判断管理员的权限中是否有某个权限。如在控制管理员的权限的数字为(13)时,判断管理员是否具有修改的权限(4)。算法为:“13 & 4==0”,假如等于0的话,表示,权限不存在,假如不等于0的话,表示,此权限已经存在。
2.分类组合
假如一个类要支持很多操作,操作和操作之间可能没有联系,可能有相反关系无法共存,可能有特殊关系必须共存,这种要分很多类还要处理联系的情况下可以考虑采用二进制来解决。
我这里的例子是java做的文件搜索,用的是递归,搜索的时候可以搜索文件、文件夹,搜索的方式可以有正则表达式匹配、以特定开始、以特定结束、以是否包含的方式。而且除了正则则要单独处理,其他方式直接可以进行组合。
通过二进制分类
Java代码
- /** 查找文件夹 */
- public static final int FIND_DIRECTORY = 1;
- /** 查找文件 */
- public static final int FIND_FILE = 2;
- /** 正则查找 */
- public static final int FIND_BY_REGEX = 4;
- /** 起始于 */
- public static final int FIND_START_WITH = 8;
- /** 结束于 */
- public static final int FIND_END_WITH = 16;
- /** 包含于 */
- public static final int FIND_CONTAIN = 32;
- // rule
- private int _rule = 0;
当程序传入规则之后,我可以很方便的加入到 _rule中
Java代码
- /** 添加规则 */
- public int ruleAdd(int r) {
- _rule = _rule | r;
- return _rule;
- }
去除 和 判断是否有这个规则
Java代码
- /** 去除规则 */
- public int ruleRemove(int r) {
- _rule = _rule & (~r);
- return _rule;
- }
- /** 是否包含规则 */
- public Boolean hasRule(int r) {
- return (_rule & r) != 0;
- }
之后处理时进行 if分类 就可以很方便
Java代码
- /**
- * 判断是否满足规则用户指定的rule (正则表达式 ______ 开始于 __________ 结束于)
- *
- * @param content
- * @return
- */
- public Boolean meetRule(File pathname) {
- Boolean result = true;
- // 查找路径
- if (hasRule(FIND_DIRECTORY)) {
- result = result && pathname.isDirectory();
- }
- // 查找文件
- if (hasRule(FIND_FILE)) {
- result = result && pathname.isFile();
- }
- String fileName = pathname.getName().toUpperCase();
- // 按照开始于查找
- if (hasRule(FIND_START_WITH)) {
- result = result && fileName.startsWith(_fix.get(FIND_START_WITH).toUpperCase());
- }
- // 按照结束于查找
- if (hasRule(FIND_END_WITH)) {
- result = result && fileName.endsWith(_fix.get(FIND_END_WITH).toUpperCase());
- }
- // 文件名包含查找
- if (hasRule(FIND_CONTAIN)) {
- result = result && fileName.contains(_fix.get(FIND_CONTAIN).toUpperCase());
- }
- // 按照正则查找 不区分大小写
- if (_rule == FIND_BY_REGEX) {
- result = result && Pattern.compile(_fix.get(FIND_BY_REGEX), Pattern.CASE_INSENSITIVE).matcher(fileName).find();
- }
- return result;
- }
大体就是这个个意思,完整代码
Java代码
- /**
- * 查找指定路径下 满足条件的文件、文件夹(不区分大小写)
- *
- * @see
- * @author kaven
- * @version 1.0, 2011-8-27
- * @since 1.0, 2011-8-27
- */
- public class PathSearch {
- /** 查找文件夹 */
- public static final int FIND_DIRECTORY = 1;
- /** 查找文件 */
- public static final int FIND_FILE = 2;
- /** 正则查找 */
- public static final int FIND_BY_REGEX = 4;
- /** 起始于 */
- public static final int FIND_START_WITH = 8;
- /** 结束于 */
- public static final int FIND_END_WITH = 16;
- /** 包含于 */
- public static final int FIND_CONTAIN = 32;
- // rule
- private int _rule = 0;
- // 用户输入的用来匹配文件名的字段 或者正则
- private Map<Integer, String> _fix = new HashMap<Integer, String>();
- // 文件
- private List<File> _files = new ArrayList<File>();
- public PathSearch() {
- }
- // public PathSearch(Map<Integer, String> aFix) {
- //
- // this._fix = aFix;
- // }
- /** 添加规则 */
- public int ruleAdd(int r) {
- _rule = _rule | r;
- return _rule;
- }
- /** 去除规则 */
- public int ruleRemove(int r) {
- _rule = _rule & (~r);
- return _rule;
- }
- /** 是否包含规则 */
- public Boolean hasRule(int r) {
- return (_rule & r) != 0;
- }
- /**
- * 判断是否满足规则用户指定的rule (正则表达式 ______ 开始于 __________ 结束于)
- *
- * @param content
- * @return
- */
- public Boolean meetRule(File pathname) {
- Boolean result = true;
- // 查找路径
- if (hasRule(FIND_DIRECTORY)) {
- result = result && pathname.isDirectory();
- }
- // 查找文件
- if (hasRule(FIND_FILE)) {
- result = result && pathname.isFile();
- }
- String fileName = pathname.getName().toUpperCase();
- // 按照开始于查找
- if (hasRule(FIND_START_WITH)) {
- result = result && fileName.startsWith(_fix.get(FIND_START_WITH).toUpperCase());
- }
- // 按照结束于查找
- if (hasRule(FIND_END_WITH)) {
- result = result && fileName.endsWith(_fix.get(FIND_END_WITH).toUpperCase());
- }
- // 文件名包含查找
- if (hasRule(FIND_CONTAIN)) {
- result = result && fileName.contains(_fix.get(FIND_CONTAIN).toUpperCase());
- }
- // 按照正则查找 不区分大小写
- if (_rule == FIND_BY_REGEX) {
- result = result && Pattern.compile(_fix.get(FIND_BY_REGEX), Pattern.CASE_INSENSITIVE).matcher(fileName).find();
- }
- return result;
- }
- /**
- * 添加规则(等价于 ruleAdd)
- *
- * @param rule
- */
- public void addRule(int rule) {
- ruleAdd(rule);
- }
- /**
- * 添加规则 和 规则验证字段
- *
- * @param rule
- * @param value
- */
- public void addRule(int rule, String value) {
- ruleAdd(rule);
- this._fix.put(rule, value);
- }
- /**
- * 根据给定的path 查找其下满足特定条件的文件、文件夹
- */
- public void findUnderPath(String path) {
- File directory = new File(path);
- if (!directory.exists()) {
- // 路径不存在
- return;
- }
- File[] files = directory.listFiles(new FileFilter() {
- @Override
- public boolean accept(File pathname) {
- return meetRule(pathname);
- }
- });
- _files = Arrays.asList(files);
- }
- /**
- * 根据指定的path 查找其下包括子文件夹 所有满足特定条件的文件、文件夹
- *
- * @return
- */
- public void findDeepUnderPath(File pathName) {
- if (!pathName.exists()) {
- return;
- }
- // 获取所有 符合规则的文件 列表
- File[] files = pathName.listFiles(new FileFilter() {
- @Override
- public boolean accept(File pathname) {
- return meetRule(pathname);
- }
- });
- // 添加到结果集列表中
- _files.addAll(Arrays.asList(files));
- // 查找所有目录
- File[] directories = pathName.listFiles(new FileFilter() {
- @Override
- public boolean accept(File pathname) {
- return pathname.isDirectory();
- }
- });
- // 获取子文件夹下的文件
- for (File directory : directories) {
- findDeepUnderPath(directory);
- }
- }
- public List<File> getFiles() {
- return _files;
- }
- @Test
- public void testFind() {
- String path = "F:\\work_tools";
- PathSearch ps = new PathSearch();
- // ps.addRule(FIND_FILE);
- ps.addRule(FIND_BY_REGEX, "[\\d]");
- // ps.addRule(FIND_END_WITH, "rar");
- // ps.findUnderPath(path);
- ps.findDeepUnderPath(new File(path));
- List<File> files = ps.getFiles();
- for (File f : files) {
- System.out.println(f.getPath());
- }
- }
- // @Test
- public void testRule() {
- System.out.println(ruleAdd(1));
- System.out.println(ruleAdd(4));
- System.out.println(ruleAdd(8));
- System.out.println(hasRule(4));
- System.out.println(ruleRemove(4));
- System.out.println(hasRule(4));
- }
- }
3.快速找出两个list(或数组)中不同的对象
一般的想法都是通过对两个list进行 循环嵌套,每找到一个,remove一个,这样的话有两个缺点:一个是速度,在最差的情况下是O(n^2),这对于数量大的是比较慢的。二是由于要remove元素,不能采用iterator尽心循环(据说采用迭代器java会有缓存优化)。
这个就可以采用二进制来解决,其实这里用二进制只是一种方式,完全可以用 权的概念,一个权设为10,一个权设为1(任意两个不相等的数都可以,如果多个list和数组的话,还是二进制方式比较清楚)。假如数组种的对象通过code来进行标示,新建一个
Java代码
- Map<String,Integer> countMap = new HashMap<String,Integer>()//key -- > code, value -- > 权
分别对两个list进行第一次循环
循环list1的时候:
Java代码
- countMap.put(code,10);
循环list2的时候:
Java代码
- if(null == countMap.get(code)){
- countMap.put(code, 0);//初始化为0
- }
- int count = countMap.get(code);//获取当前权
- countMap.put(code, count + 1);//更新权
这样一来,所有list1独有的,countMap表现为Value为1,list2独有的,countMap表现为Value为10,共有的表现为Value为11
然后进行第二次循环,将list1、list2根据code进行分类,组合成两个HashMap,以方便根据code找出code相同的部分(code相同不代表其他属性也相同,实际处理中可能会有用,不管你用没用到,反正我用到了)和code不同的部分。
之后就是 根据找出来的code,各自的map中获取对应的对象了。
复制度O(2n)
我能想到的是这个方法,不知道有没有更好的,望提示!!!
上代码:
Java代码
- /**
- * 通过3次循环,对field 进行快速分类,找出彼此code不同的TableField
- * @author qihuan
- *
- */
- public class QuickDiff {
- private List<TableField> oldFieldPop = new ArrayList<TableField>();
- private List<TableField> newFieldAppend = new ArrayList<TableField>();
- private List<String> commonCode = new ArrayList<String>();
- private Map<String, TableField> newFieldMap;
- private Map<String, TableField> oldFieldMap;
- public QuickDiff(){
- }
- /**
- * 通过3次循环,对field 进行快速分类
- * @param oldFields
- * @param newFields
- */
- public void doDiff(List<TableField> oldFields,List<TableField> newFields){
- // key:desc -- value:对应出现次数
- Map<String,Integer> countMap = new HashMap<String, Integer>();
- addToMap(countMap,oldFields,1);//old 权为 1
- addToMap(countMap,newFields,10);//new 权为10
- newFieldMap = turnToMapByCode(newFields);
- oldFieldMap = turnToMapByCode(oldFields);
- //对 独有的code进行分类
- for(String code : countMap.keySet()){
- int value = countMap.get(code);
- if(value == 11){
- commonCode.add(code);
- //do nothing
- }else if(value == 10){
- newFieldAppend.add(newFieldMap.get(code));
- }else if(value == 1){
- oldFieldPop.add(oldFieldMap.get(code));
- }
- }
- }
- /**
- * 按照 code 进行分类
- * @param fields
- * @return
- */
- private Map<String, TableField> turnToMapByCode(List<TableField> fields){
- Map<String, TableField> fieldMap = new HashMap<String, TableField>();
- for(TableField tf : fields){
- String code = tf.getCode();
- fieldMap.put(code, tf);
- }
- return fieldMap;
- }
- /**
- *
- * @param countMap 计数map
- * @param fields
- * @param value 权
- */
- private void addToMap(Map<String, Integer> countMap, List<TableField> fields, int value) {
- for(TableField tf : fields){
- String code = tf.getCode();
- if(null == countMap.get(code)){
- countMap.put(code, 0);
- }
- int count = countMap.get(code);//获取当前权
- countMap.put(code, count + value);//更新权
- }
- }
- /**
- * old 独有的
- * @return
- */
- public List<TableField> getOldFieldPop() {
- return oldFieldPop;
- }
- /**
- * new 独有的
- * @return
- */
- public List<TableField> getNewFieldAppend() {
- return newFieldAppend;
- }
- /**
- * 共有的
- * @return
- */
- public List<String> getCommonCode() {
- return commonCode;
- }
- /**
- * newField to Map
- * @return
- */
- public Map<String, TableField> getNewFieldMap() {
- return newFieldMap;
- }
- /**
- * oldField to Map
- * @return
- */
- public Map<String, TableField> getOldFieldMap() {
- return oldFieldMap;
- }
- }