zoukankan      html  css  js  c++  java
  • 位运算的应用

    平常都很少用到位运算,这里介绍一种jdk使用位运算的小案例。它是用位运算来优化一个类所占的大小。下面介绍:

    • 什么情况下,符合这种优化条件;
    • 用具体的例子来介绍;

    优化情况

    假设一个类需要有很多boolean类型得属性,如果直接用boolean类型,那么这个类会在内存中占用很大空间。通常情况下,一个boolean类型属性会占4个字节。但这不是一定得,JAVA得boolean属性占用字节不一定。这时候,使用多个boolean类型的属性就占用很多内存。

    在这种情况下,可以使用字节得0、1来代表true、false。使用位运算来获取、设置boolean属性得值。比如说:我们可以使用int来存储32个boolean属性,这样就会节省大量的内存。

    JDK中有具体得例子,如java.lang.reflect.Modifier

    具体例子

    假设一个猫有三个属性:cutefatwhite,其取值只有俩种true、false。现在用int的后面三个位来存储这三个类型的值。
    即:在int最后一个位作为cute属性得值;倒数第二位作为fat属性得值;倒数第三位作为white属性得值。

    1、创建int属性得值,作为存储这三个属性得属性值

    public class Cat {
        // 存储三个boolean属性得值
        private int properties = 0;
    }
    

    2、设置三个int属性作为三个属性都为true;这是为了后期方便设置值

    public class Cat {
        private static int CUTE = 0x1;
        private static int FAT = 0x2;
        private static int WHITE = 0x4;
        private int properties = 0;
    }
    

    3、以cute属性的获取、设置
    (1)获取值的时候
    指获取properties属性的最后一位的值,需要注意的是获取最后一位值得时候,不能影响其他位得值!!!

        /**
         * 这只猫萌吗?请在此处使用位运算读取properties,得到猫是否萌的结果
         *
         * @return 萌则返回true,否则返回false
         */
        public boolean isCute() {
            return (properties & Cat.CUTE) != 0;
        }
    

    使用与运算得时候,其他位不受影响;最后一位也是取决于properties最后一位得值

    (2)设置值的时候
    在设置properties属性得最后一位得值,需要注意得是设置最后一位的值的时候,不能影响其他位得值!!!

        /**
         * 使用位运算设置猫咪萌的属性
         *
         * @param cute true为萌,false为不萌
         */
        public void setCute(boolean cute) {
            if (cute == true){
                properties = properties | Cat.CUTE;
            } else {
                properties = properties & (~Cat.CUTE);
            }
        }
    

    4、设置其他属性

        /**
         * 使用位运算设置猫咪胖的属性
         *
         * @param fat true为胖,false为不胖
         */
        public void setFat(boolean fat) {
            if (fat){
                properties = properties | Cat.FAT;
            } else {
                properties = properties & (~Cat.FAT);
            }
        }
    
        /**
         * 这只猫胖吗?请在此处使用位运算读取properties,得到猫是否胖的结果
         *
         * @return 胖则返回true,否则返回false
         */
        public boolean isFat() {
            return (properties & Cat.FAT) != 0;
        }
    
        /**
         * 使用位运算设置猫咪白的属性
         *
         * @param white true为白,false为不白
         */
        public void setWhite(boolean white) {
            if (white){
                properties = properties | Cat.WHITE;
            } else {
                properties = properties & (~Cat.WHITE);
            }
        }
    
        /**
         * 这只猫白吗?请在此处使用位运算读取properties,得到猫是否白的结果
         *
         * @return 白则返回true,否则返回false
         */
        public boolean isWhite() {
            return (properties & Cat.WHITE) != 0;
        }
    

    总结

    一般情况下,获取值使用&;设置值使用|~&。关键就是在使用位运算的时候,只影响指定位置的值,其他位置的值不能改变。完整代码如下:

    public class Cat {
        private static int CUTE = 0x1;
        private static int FAT = 0x2;
        private static int WHITE = 0x4;
        private int properties = 0;
    
        /**
         * 使用位运算设置猫咪萌的属性
         *
         * @param cute true为萌,false为不萌
         */
        public void setCute(boolean cute) {
            if (cute == true){
                properties = properties | Cat.CUTE;
            } else {
                properties = properties & (~Cat.CUTE);
            }
        }
    
        /**
         * 这只猫萌吗?请在此处使用位运算读取properties,得到猫是否萌的结果
         *
         * @return 萌则返回true,否则返回false
         */
        public boolean isCute() {
            return (properties & Cat.CUTE) != 0;
        }
    
        /**
         * 使用位运算设置猫咪胖的属性
         *
         * @param fat true为胖,false为不胖
         */
        public void setFat(boolean fat) {
            if (fat){
                properties = properties | Cat.FAT;
            } else {
                properties = properties & (~Cat.FAT);
            }
        }
    
        /**
         * 这只猫胖吗?请在此处使用位运算读取properties,得到猫是否胖的结果
         *
         * @return 胖则返回true,否则返回false
         */
        public boolean isFat() {
            return (properties & Cat.FAT) != 0;
        }
    
        /**
         * 使用位运算设置猫咪白的属性
         *
         * @param white true为白,false为不白
         */
        public void setWhite(boolean white) {
            if (white){
                properties = properties | Cat.WHITE;
            } else {
                properties = properties & (~Cat.WHITE);
            }
        }
    
        /**
         * 这只猫白吗?请在此处使用位运算读取properties,得到猫是否白的结果
         *
         * @return 白则返回true,否则返回false
         */
        public boolean isWhite() {
            return (properties & Cat.WHITE) != 0;
        }
    
        public static void main(String[] args) {
            Cat cat = new Cat();
            cat.setCute(true);
            cat.setFat(true);
            cat.setWhite(false);
            System.out.println("这只猫萌吗:" + cat.isCute());
            System.out.println("这只猫胖吗:" + cat.isFat());
            System.out.println("这只猫白吗:" + cat.isWhite());
        }
    }
    

    位运算的一些坑

    交换俩个值得功能可以用位运算这种骚操作完成。比如:

        public static void main(String[] args) {
            Main main = new Main();
            int[] arr = {1,2};
            main.test(0,1,arr);
        }
    
        public void test(int a, int b, int[] arr){
            arr[a] = arr[a] ^ arr[b];
            arr[b] = arr[a] ^ arr[b];
            arr[a] = arr[a] ^ arr[b];
            System.out.println(Arrays.toString(arr));//[2,1]
        }
    

    但这里有个坑,如果你传得俩个地址是一样得话,就会出错:

        public static void main(String[] args) {
            Main main = new Main();
            int[] arr = {1,2};
            main.test(0,0,arr);
        }
    
        public void test(int a, int b, int[] arr){
            arr[a] = arr[a] ^ arr[b];
            arr[b] = arr[a] ^ arr[b];
            arr[a] = arr[a] ^ arr[b];
            System.out.println(Arrays.toString(arr));//[0,1]
        }
    
  • 相关阅读:
    MSSQL安全审计文件执行Rootkit-WarSQLKit
    组建自己的局域网服务器
    python openpyxl表格样式设置
    ssh 和 scp 命令访问非默认22端口。
    set | grep IFS
    Python: check if key exists in dictionary (6 Ways)
    在线Jinja2解析器
    FastApi教程|测试WebSockets
    QT Qstring的用法
    QT UI拖拽方法
  • 原文地址:https://www.cnblogs.com/fourther/p/13698424.html
Copyright © 2011-2022 走看看