用二进制的与、或、非运算方便的解决实际问题

 转载 http://qihigh-hotmail-com.iteye.com/blog/1329696

二进制的与、或、非运算特殊用法的不同运用场合:

1.权限控制 
    下面我用几个数字来代表增,删,改,查。(注:1带有有权限,有几个1,就代表有几个权限,1的位置不同,所带表的权限也不同) 
Java代码    收藏代码
  1. 1---------增--------(转二进制)-----(0001)  
  2. 2---------删----------------------(0010)  
  3. 4--------改----------------------(0100)  
  4. 8--------查----------------------(1000)  


管理员拥有所有的权限,所以,控制管理员的权限的数字为(15),转化二进制的格式为:(1111)。算法为:“1|2|4|8“ 
撤销管理员的删权限(2),控制管理员的权限的数字为(13),转化二进制的格式为:(1101)。算法为:”15 & (~2)” 
判断管理员的权限中是否有某个权限。如在控制管理员的权限的数字为(13)时,判断管理员是否具有修改的权限(4)。算法为:“13 & 4==0”,假如等于0的话,表示,权限不存在,假如不等于0的话,表示,此权限已经存在。
 

2.分类组合 
    假如一个类要支持很多操作,操作和操作之间可能没有联系,可能有相反关系无法共存,可能有特殊关系必须共存,这种要分很多类还要处理联系的情况下可以考虑采用二进制来解决。 
    我这里的例子是java做的文件搜索,用的是递归,搜索的时候可以搜索文件、文件夹,搜索的方式可以有正则表达式匹配、以特定开始、以特定结束、以是否包含的方式。而且除了正则则要单独处理,其他方式直接可以进行组合。 
    通过二进制分类
 
Java代码    收藏代码
  1. /** 查找文件夹 */  
  2. public static final int      FIND_DIRECTORY  = 1;  
  3. /** 查找文件 */  
  4. public static final int      FIND_FILE       = 2;  
  5. /** 正则查找 */  
  6. public static final int      FIND_BY_REGEX   = 4;  
  7. /** 起始于 */  
  8. public static final int      FIND_START_WITH = 8;  
  9. /** 结束于 */  
  10. public static final int      FIND_END_WITH   = 16;  
  11. /** 包含于 */  
  12. public static final int      FIND_CONTAIN    = 32;  
  13. // rule  
  14. private int           _rule        = 0;  

     当程序传入规则之后,我可以很方便的加入到 _rule中 
Java代码    收藏代码
  1. /** 添加规则 */  
  2. public int ruleAdd(int r) {  
  3.   
  4.   _rule = _rule | r;  
  5.   return _rule;  
  6. }  

      去除 和 判断是否有这个规则 

Java代码    收藏代码
  1. /** 去除规则 */  
  2. public int ruleRemove(int r) {  
  3.   
  4.   _rule = _rule & (~r);  
  5.   return _rule;  
  6. }  
  7.   
  8. /** 是否包含规则 */  
  9. public Boolean hasRule(int r) {  
  10.   
  11.   return (_rule & r) != 0;  
  12. }  

     之后处理时进行 if分类 就可以很方便 
Java代码    收藏代码
  1. /** 
  2.     * 判断是否满足规则用户指定的rule (正则表达式 ______ 开始于 __________ 结束于) 
  3.     * 
  4.     * @param content 
  5.     * @return 
  6.     */  
  7.    public Boolean meetRule(File pathname) {  
  8.   
  9.      Boolean result = true;  
  10.      // 查找路径  
  11.      if (hasRule(FIND_DIRECTORY)) {  
  12.          result = result && pathname.isDirectory();  
  13.      }  
  14.      // 查找文件  
  15.      if (hasRule(FIND_FILE)) {  
  16.          result = result && pathname.isFile();  
  17.      }  
  18.      String fileName = pathname.getName().toUpperCase();  
  19.      // 按照开始于查找  
  20.      if (hasRule(FIND_START_WITH)) {  
  21.          result = result && fileName.startsWith(_fix.get(FIND_START_WITH).toUpperCase());  
  22.      }  
  23.      // 按照结束于查找  
  24.      if (hasRule(FIND_END_WITH)) {  
  25.          result = result && fileName.endsWith(_fix.get(FIND_END_WITH).toUpperCase());  
  26.      }  
  27.      // 文件名包含查找  
  28.      if (hasRule(FIND_CONTAIN)) {  
  29.          result = result && fileName.contains(_fix.get(FIND_CONTAIN).toUpperCase());  
  30.      }  
  31.      // 按照正则查找 不区分大小写  
  32.      if (_rule == FIND_BY_REGEX) {  
  33.          result = result && Pattern.compile(_fix.get(FIND_BY_REGEX), Pattern.CASE_INSENSITIVE).matcher(fileName).find();  
  34.      }  
  35.      return result;  
  36.    }  


大体就是这个个意思,完整代码 
Java代码    收藏代码
  1. /** 
  2.  * 查找指定路径下 满足条件的文件、文件夹(不区分大小写) 
  3.  * 
  4.  * @see 
  5.  * @author kaven 
  6.  * @version 1.0, 2011-8-27 
  7.  * @since 1.0, 2011-8-27 
  8.  */  
  9. public class PathSearch {  
  10.   
  11.     /** 查找文件夹 */  
  12.     public static final int      FIND_DIRECTORY  = 1;  
  13.     /** 查找文件 */  
  14.     public static final int      FIND_FILE       = 2;  
  15.     /** 正则查找 */  
  16.     public static final int      FIND_BY_REGEX   = 4;  
  17.     /** 起始于 */  
  18.     public static final int      FIND_START_WITH = 8;  
  19.     /** 结束于 */  
  20.     public static final int      FIND_END_WITH   = 16;  
  21.     /** 包含于 */  
  22.     public static final int      FIND_CONTAIN    = 32;  
  23.   
  24.     // rule  
  25.     private int           _rule        = 0;  
  26.     // 用户输入的用来匹配文件名的字段 或者正则  
  27.     private Map<Integer, String> _fix         = new HashMap<Integer, String>();  
  28.     // 文件  
  29.     private List<File>     _files = new ArrayList<File>();  
  30.   
  31.     public PathSearch() {  
  32.   
  33.     }  
  34.   
  35.     // public PathSearch(Map<Integer, String> aFix) {  
  36.     //  
  37.     // this._fix = aFix;  
  38.     // }  
  39.   
  40.     /** 添加规则 */  
  41.     public int ruleAdd(int r) {  
  42.   
  43.       _rule = _rule | r;  
  44.       return _rule;  
  45.     }  
  46.   
  47.     /** 去除规则 */  
  48.     public int ruleRemove(int r) {  
  49.   
  50.       _rule = _rule & (~r);  
  51.       return _rule;  
  52.     }  
  53.   
  54.     /** 是否包含规则 */  
  55.     public Boolean hasRule(int r) {  
  56.   
  57.       return (_rule & r) != 0;  
  58.     }  
  59.   
  60.     /** 
  61.      * 判断是否满足规则用户指定的rule (正则表达式 ______ 开始于 __________ 结束于) 
  62.      * 
  63.      * @param content 
  64.      * @return 
  65.      */  
  66.     public Boolean meetRule(File pathname) {  
  67.   
  68.       Boolean result = true;  
  69.       // 查找路径  
  70.       if (hasRule(FIND_DIRECTORY)) {  
  71.           result = result && pathname.isDirectory();  
  72.       }  
  73.       // 查找文件  
  74.       if (hasRule(FIND_FILE)) {  
  75.           result = result && pathname.isFile();  
  76.       }  
  77.       String fileName = pathname.getName().toUpperCase();  
  78.       // 按照开始于查找  
  79.       if (hasRule(FIND_START_WITH)) {  
  80.           result = result && fileName.startsWith(_fix.get(FIND_START_WITH).toUpperCase());  
  81.       }  
  82.       // 按照结束于查找  
  83.       if (hasRule(FIND_END_WITH)) {  
  84.           result = result && fileName.endsWith(_fix.get(FIND_END_WITH).toUpperCase());  
  85.       }  
  86.       // 文件名包含查找  
  87.       if (hasRule(FIND_CONTAIN)) {  
  88.           result = result && fileName.contains(_fix.get(FIND_CONTAIN).toUpperCase());  
  89.       }  
  90.       // 按照正则查找 不区分大小写  
  91.       if (_rule == FIND_BY_REGEX) {  
  92.           result = result && Pattern.compile(_fix.get(FIND_BY_REGEX), Pattern.CASE_INSENSITIVE).matcher(fileName).find();  
  93.       }  
  94.       return result;  
  95.     }  
  96.   
  97.     /** 
  98.      * 添加规则(等价于 ruleAdd) 
  99.      * 
  100.      * @param rule 
  101.      */  
  102.     public void addRule(int rule) {  
  103.   
  104.       ruleAdd(rule);  
  105.     }  
  106.   
  107.     /** 
  108.      * 添加规则 和 规则验证字段 
  109.      * 
  110.      * @param rule 
  111.      * @param value 
  112.      */  
  113.     public void addRule(int rule, String value) {  
  114.   
  115.       ruleAdd(rule);  
  116.       this._fix.put(rule, value);  
  117.     }  
  118.   
  119.     /** 
  120.      * 根据给定的path 查找其下满足特定条件的文件、文件夹 
  121.      */  
  122.     public void findUnderPath(String path) {  
  123.   
  124.       File directory = new File(path);  
  125.       if (!directory.exists()) {  
  126.           // 路径不存在  
  127.           return;  
  128.       }  
  129.       File[] files = directory.listFiles(new FileFilter() {  
  130.   
  131.           @Override  
  132.           public boolean accept(File pathname) {  
  133.   
  134.             return meetRule(pathname);  
  135.           }  
  136.       });  
  137.       _files = Arrays.asList(files);  
  138.     }  
  139.   
  140.     /** 
  141.      * 根据指定的path 查找其下包括子文件夹 所有满足特定条件的文件、文件夹 
  142.      * 
  143.      * @return 
  144.      */  
  145.     public void findDeepUnderPath(File pathName) {  
  146.   
  147.       if (!pathName.exists()) {  
  148.           return;  
  149.       }  
  150.       // 获取所有 符合规则的文件 列表  
  151.       File[] files = pathName.listFiles(new FileFilter() {  
  152.   
  153.           @Override  
  154.           public boolean accept(File pathname) {  
  155.   
  156.             return meetRule(pathname);  
  157.           }  
  158.       });  
  159.       // 添加到结果集列表中  
  160.       _files.addAll(Arrays.asList(files));  
  161.       // 查找所有目录  
  162.       File[] directories = pathName.listFiles(new FileFilter() {  
  163.   
  164.           @Override  
  165.           public boolean accept(File pathname) {  
  166.   
  167.             return pathname.isDirectory();  
  168.           }  
  169.       });  
  170.       // 获取子文件夹下的文件  
  171.       for (File directory : directories) {  
  172.           findDeepUnderPath(directory);  
  173.       }  
  174.     }  
  175.   
  176.     public List<File> getFiles() {  
  177.   
  178.       return _files;  
  179.     }  
  180.   
  181.     @Test  
  182.     public void testFind() {  
  183.   
  184.       String path = "F:\\work_tools";  
  185.       PathSearch ps = new PathSearch();  
  186.   
  187.       // ps.addRule(FIND_FILE);  
  188.       ps.addRule(FIND_BY_REGEX, "[\\d]");  
  189. //     ps.addRule(FIND_END_WITH, "rar");  
  190.   
  191.       // ps.findUnderPath(path);  
  192.       ps.findDeepUnderPath(new File(path));  
  193.       List<File> files = ps.getFiles();  
  194.       for (File f : files) {  
  195.           System.out.println(f.getPath());  
  196.       }  
  197.     }  
  198.   
  199. //    @Test  
  200.     public void testRule() {  
  201.   
  202.       System.out.println(ruleAdd(1));  
  203.       System.out.println(ruleAdd(4));  
  204.       System.out.println(ruleAdd(8));  
  205.       System.out.println(hasRule(4));  
  206.       System.out.println(ruleRemove(4));  
  207.       System.out.println(hasRule(4));  
  208.     }  
  209. }  

3.快速找出两个list(或数组)中不同的对象 
    一般的想法都是通过对两个list进行 循环嵌套,每找到一个,remove一个,这样的话有两个缺点:一个是速度,在最差的情况下是O(n^2),这对于数量大的是比较慢的。二是由于要remove元素,不能采用iterator尽心循环(据说采用迭代器java会有缓存优化)。 
      这个就可以采用二进制来解决,其实这里用二进制只是一种方式,完全可以用 权的概念,一个权设为10,一个权设为1
任意两个不相等的数都可以,如果多个list和数组的话,还是二进制方式比较清楚 )。 假如数组种的对象通过code来进行标示,新建一个 
Java代码    收藏代码
  1. Map<String,Integer> countMap = new HashMap<String,Integer>()//key -- > code, value -- > 权  

分别对两个list进行第一次循环 
   循环list1的时候:
 
Java代码    收藏代码
  1. countMap.put(code,10);  

    循环list2的时候: 

Java代码    收藏代码
  1. if(null == countMap.get(code)){  
  2.    countMap.put(code, 0);//初始化为0  
  3. }  
  4. int count = countMap.get(code);//获取当前权  
  5. 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代码    收藏代码
  1. /** 
  2.  * 通过3次循环,对field 进行快速分类,找出彼此code不同的TableField 
  3.  * @author qihuan 
  4.  * 
  5.  */  
  6. public class QuickDiff {  
  7.     private List<TableField> oldFieldPop = new ArrayList<TableField>();  
  8.     private List<TableField> newFieldAppend = new ArrayList<TableField>();  
  9.     private List<String> commonCode = new ArrayList<String>();  
  10.     private Map<String, TableField> newFieldMap;  
  11.     private Map<String, TableField> oldFieldMap;  
  12.       
  13.     public QuickDiff(){  
  14.     }  
  15.     /** 
  16.      * 通过3次循环,对field 进行快速分类 
  17.      * @param oldFields 
  18.      * @param newFields 
  19.      */  
  20.     public void doDiff(List<TableField> oldFields,List<TableField> newFields){  
  21.     // key:desc -- value:对应出现次数  
  22.     Map<String,Integer> countMap = new HashMap<String, Integer>();  
  23.     addToMap(countMap,oldFields,1);//old 权为 1  
  24.     addToMap(countMap,newFields,10);//new 权为10  
  25.       
  26.     newFieldMap = turnToMapByCode(newFields);  
  27.     oldFieldMap = turnToMapByCode(oldFields);  
  28.     //对 独有的code进行分类  
  29.     for(String code : countMap.keySet()){  
  30.         int value = countMap.get(code);  
  31.         if(value == 11){  
  32.         commonCode.add(code);  
  33.         //do nothing  
  34.         }else if(value == 10){  
  35.         newFieldAppend.add(newFieldMap.get(code));  
  36.         }else if(value == 1){  
  37.         oldFieldPop.add(oldFieldMap.get(code));  
  38.         }  
  39.     }  
  40.     }  
  41.       
  42.     /** 
  43.      * 按照 code 进行分类 
  44.      * @param fields 
  45.      * @return 
  46.      */  
  47.     private Map<String, TableField> turnToMapByCode(List<TableField> fields){  
  48.     Map<String, TableField> fieldMap = new HashMap<String, TableField>();  
  49.     for(TableField tf : fields){  
  50.         String code = tf.getCode();  
  51.         fieldMap.put(code, tf);  
  52.     }  
  53.     return fieldMap;  
  54.     }  
  55.     /** 
  56.      *  
  57.      * @param countMap 计数map 
  58.      * @param fields  
  59.      * @param value 权 
  60.      */  
  61.     private void addToMap(Map<String, Integer> countMap, List<TableField> fields, int value) {  
  62.     for(TableField tf : fields){  
  63.         String code = tf.getCode();  
  64.         if(null == countMap.get(code)){  
  65.         countMap.put(code, 0);  
  66.         }  
  67.         int count = countMap.get(code);//获取当前权  
  68.         countMap.put(code, count + value);//更新权  
  69.     }  
  70.     }  
  71.     /** 
  72.      * old 独有的 
  73.      * @return 
  74.      */  
  75.     public List<TableField> getOldFieldPop() {  
  76.       
  77.         return oldFieldPop;  
  78.     }  
  79.     /** 
  80.      * new 独有的 
  81.      * @return 
  82.      */  
  83.     public List<TableField> getNewFieldAppend() {  
  84.       
  85.         return newFieldAppend;  
  86.     }  
  87.     /** 
  88.      * 共有的 
  89.      * @return 
  90.      */  
  91.     public List<String> getCommonCode() {  
  92.       
  93.         return commonCode;  
  94.     }  
  95.     /** 
  96.      * newField to Map 
  97.      * @return 
  98.      */  
  99.     public Map<String, TableField> getNewFieldMap() {  
  100.       
  101.         return newFieldMap;  
  102.     }  
  103.     /** 
  104.      * oldField to Map 
  105.      * @return 
  106.      */  
  107.     public Map<String, TableField> getOldFieldMap() {  
  108.       
  109.         return oldFieldMap;  
  110.     }  
  111.       
  112. }  

你可能感兴趣的:(二进制)