• java.util.BitSet 详细分析 学习笔记


    1,BitSet类
        大小可动态改变, 取值为true或false的位集合。用于表示一组布尔标志。   

    此类实现了一个按需增长的位向量。位 set 的每个组件都有一个 boolean 值。用非负的整数将 BitSet 的位编入索引。可以对每个编入索引的位进行测试、设置或者清除。通过逻辑与、逻辑或和逻辑异或操作,可以使用一个 BitSet 修改另一个 BitSet 的内容。

    默认情况下,set 中所有位的初始值都是 false。

      每个位 set 都有一个当前大小,也就是该位 set 当前所用空间的位数。注意,这个大小与位 set 的实现有关,所以它可能随实现的不同而更改。位 set 的长度与位 set 的逻辑长度有关,并且是与实现无关而定义的。

       除非另行说明,否则将 null 参数传递给 BitSet 中的任何方法都将导致 NullPointerException。 在没有外部同步的情况下,多个线程操作一个 BitSet 是不安全的。

    2,构造函数: BitSet() or BitSet(int nbits)

    3,方法:

    public void set(int pos): 位置pos的字位设置为true。 
    public void set(int bitIndex, boolean value) 将指定索引处的位设置为指定的值。 
    public void clear(int pos): 位置pos的字位设置为false。
    public void clear() : 将此 BitSet 中的所有位设置为 false。 
    public int cardinality() 返回此 BitSet 中设置为 true 的位数。 
    public boolean get(int pos): 返回位置是pos的字位值。 
    public void and(BitSet other): other同该字位集进行与操作,结果作为该字位集的新值。 
    public void or(BitSet other): other同该字位集进行或操作,结果作为该字位集的新值。 
    public void xor(BitSet other): other同该字位集进行异或操作,结果作为该字位集的新值。
    public void andNot(BitSet set) 清除此 BitSet 中所有的位,set - 用来屏蔽此 BitSet 的 BitSet
    public int size(): 返回此 BitSet 表示位值时实际使用空间的位数。
    public int length() 返回此 BitSet 的“逻辑大小”:BitSet 中最高设置位的索引加 1。 
    public int hashCode(): 返回该集合Hash 码, 这个码同集合中的字位值有关。 
    public boolean equals(Object other): 如果other中的字位同集合中的字位相同,返回true。 
    public Object clone() 克隆此 BitSet,生成一个与之相等的新 BitSet。 
    public String toString() 返回此位 set 的字符串表示形式。

    例1:标明一个字符串中用了哪些字符

    复制代码
    import java.util.BitSet;
    public class WhichChars{
       private BitSet used = new BitSet();
       public WhichChars(String str){
          for(int i=0;i< str.length();i++)
            used.set(str.charAt(i));  // set bit for char
       }
        public String toString(){
             String desc="[";
             int size=used.size();
              for(int i=0;i< size;i++){
                 if(used.get(i))
                     desc+=(char)i;
                }
                 return desc+"]";
             }
        public static void main(String args[]){
            WhichChars w=new WhichChars("How do you do");
            System.out.println(w);
        }
       }
    复制代码

    运行:
    C:work>java WhichChars

    [ Hdouwy]

    4

    java.util.BitSet可以按位存储。
    计算机中一个字节(byte)占8位(bit),我们java中数据至少按字节存储的,
    比如一个int占4个字节。
    如果遇到大的数据量,这样必然会需要很大存储空间和内存。
    如何减少数据占用存储空间和内存可以用算法解决。
    java.util.BitSet就提供了这样的算法。
    比如有一堆数字,需要存储,source=[3,5,6,9]
    用int就需要4*4个字节。
    java.util.BitSet可以存true/false。
    如果用java.util.BitSet,则会少很多,其原理是:
    1,先找出数据中最大值maxvalue=9
    2,声明一个BitSet bs,它的size是maxvalue+1=10
    3,遍历数据source,bs[source[i]]设置成true.
    最后的值是:
    (0为false;1为true)
    bs [0,0,0,1,0,1,1,0,0,1]
                    3,   5,6,       9

    这样一个本来要int型需要占4字节共32位的数字现在只用了1位!
    比例32:1  
    这样就省下了很大空间。

    例子:

    复制代码
    package com;  
      
    import java.util.BitSet;  
      
    public class MainTestThree {  
      
        /**  
         * @param args  
         */  
        public static void main(String[] args) {  
            BitSet bm=new BitSet();  
            System.out.println(bm.isEmpty()+"--"+bm.size());  
            bm.set(0);  
            System.out.println(bm.isEmpty()+"--"+bm.size());  
            bm.set(1);  
            System.out.println(bm.isEmpty()+"--"+bm.size());  
            System.out.println(bm.get(65));  
            System.out.println(bm.isEmpty()+"--"+bm.size());  
            bm.set(65);  
            System.out.println(bm.isEmpty()+"--"+bm.size());  
        }  
      
    }  

    代码示例

    
    
    package util;
    
    import java.util.Arrays;
    import java.util.BitSet;
    
    public class BitSetDemo {
    
    	/**
    	 * 求一个字符串包含的char
    	 * 
    	 */
    	public static void containChars(String str) {
    		BitSet used = new BitSet();
    		for (int i = 0; i < str.length(); i++)
    			used.set(str.charAt(i)); // set bit for char
    
    		StringBuilder sb = new StringBuilder();
    		sb.append("[");
    		int size = used.size();
    		System.out.println(size);
    		for (int i = 0; i < size; i++) {
    			if (used.get(i)) {
    				sb.append((char) i);
    			}
    		}
    		sb.append("]");
    		System.out.println(sb.toString());
    	}
    
    	/**
    	 * 求素数 有无限个。一个大于1的自然数,如果除了1和它本身外,不能被其他自然数整除(除0以外)的数称之为素数(质数) 否则称为合数
    	 */
    	public static void computePrime() {
    		BitSet sieve = new BitSet(1024);
    		int size = sieve.size();
    		for (int i = 2; i < size; i++)
    			sieve.set(i);
    		int finalBit = (int) Math.sqrt(sieve.size());
    
    		for (int i = 2; i < finalBit; i++)
    			if (sieve.get(i))
    				for (int j = 2 * i; j < size; j += i)
    					sieve.clear(j);
    
    		int counter = 0;
    		for (int i = 1; i < size; i++) {
    			if (sieve.get(i)) {
    				System.out.printf("%5d", i);
    				if (++counter % 15 == 0)
    					System.out.println();
    			}
    		}
    		System.out.println();
    	}
    	
    	/**
    	 * 进行数字排序
    	 */
    	public static void sortArray() {
    		int[] array = new int[] { 423, 700, 9999, 2323, 356, 6400, 1,2,3,2,2,2,2 };
    		BitSet bitSet = new BitSet(2 << 13);
    		// 虽然可以自动扩容,但尽量在构造时指定估算大小,默认为64
    		System.out.println("BitSet size: " + bitSet.size());
    
    		for (int i = 0; i < array.length; i++) {
    			bitSet.set(array[i]);
    		}
    		//剔除重复数字后的元素个数
    		int bitLen=bitSet.cardinality();	
    
    		//进行排序,即把bit为true的元素复制到另一个数组
    		int[] orderedArray = new int[bitLen];
    		int k = 0;
    		for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) {
    			orderedArray[k++] = i;
    		}
    
    		System.out.println("After ordering: ");
    		for (int i = 0; i < bitLen; i++) {
    			System.out.print(orderedArray[i] + "	");
    		}
    		
    		System.out.println("iterate over the true bits in a BitSet");
    		//或直接迭代BitSet中bit为true的元素iterate over the true bits in a BitSet
    		for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) {
    			System.out.print(i+"	");
    		}
    		System.out.println("---------------------------");
    	}
    	
    	/**
    	 * 将BitSet对象转化为ByteArray
    	 * @param bitSet
    	 * @return
    	 */
    	public static byte[] bitSet2ByteArray(BitSet bitSet) {
            byte[] bytes = new byte[bitSet.size() / 8];
            for (int i = 0; i < bitSet.size(); i++) {
                int index = i / 8;
                int offset = 7 - i % 8;
                bytes[index] |= (bitSet.get(i) ? 1 : 0) << offset;
            }
            return bytes;
        }
     
    	/**
    	 * 将ByteArray对象转化为BitSet
    	 * @param bytes
    	 * @return
    	 */
        public static BitSet byteArray2BitSet(byte[] bytes) {
            BitSet bitSet = new BitSet(bytes.length * 8);
            int index = 0;
            for (int i = 0; i < bytes.length; i++) {
                for (int j = 7; j >= 0; j--) {
                    bitSet.set(index++, (bytes[i] & (1 << j)) >> j == 1 ? true
                            : false);
                }
            }
            return bitSet;
        }
    	
    	/**
    	 * 简单使用示例
    	 */
    	public static void simpleExample() {
    		String names[] = { "Java", "Source", "and", "Support" };
    		BitSet bits = new BitSet();
    		for (int i = 0, n = names.length; i < n; i++) {
    			if ((names[i].length() % 2) == 0) {
    				bits.set(i);
    			}
    		}
    
    		System.out.println(bits);
    		System.out.println("Size : " + bits.size());
    		System.out.println("Length: " + bits.length());
    		for (int i = 0, n = names.length; i < n; i++) {
    			if (!bits.get(i)) {
    				System.out.println(names[i] + " is odd");
    			}
    		}
    		BitSet bites = new BitSet();
    		bites.set(0);
    		bites.set(1);
    		bites.set(2);
    		bites.set(3);
    		bites.andNot(bits);
    		System.out.println(bites);
    	}
    
    	public static void main(String args[]) {
    		//BitSet使用示例
    		BitSetDemo.containChars("How do you do? 你好呀");
    		BitSetDemo.computePrime();
    		BitSetDemo.sortArray();
    		BitSetDemo.simpleExample();
    		
    		
    		//BitSet与Byte数组互转示例
    		BitSet bitSet = new BitSet();
            bitSet.set(3, true);
            bitSet.set(98, true);
            System.out.println(bitSet.size()+","+bitSet.cardinality());
            //将BitSet对象转成byte数组
            byte[] bytes = BitSetDemo.bitSet2ByteArray(bitSet);
            System.out.println(Arrays.toString(bytes));
             
            //在将byte数组转回来
            bitSet = BitSetDemo.byteArray2BitSet(bytes);
            System.out.println(bitSet.size()+","+bitSet.cardinality());
            System.out.println(bitSet.get(3));
            System.out.println(bitSet.get(98));
            for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet.nextSetBit(i + 1)) {
    			System.out.print(i+"	");
    		}
    	}
    }
     
    复制代码
    求关注:www.mayou18.com JAVA技术交流群:516348359 Jstorm技术交流群:199260183
  • 相关阅读:
    我的2007, 兼谈些对技术的看法
    回帖整理: 关于"学习Java社区"更清晰的思路
    回帖整理: 创业心态
    我的世界观 by 爱因斯坦
    回帖整理: 论团队中的设计工作
    请大家帮我一个忙
    回帖整理: Java社区有什么可学的?
    SSL原理及应用(1)SSL协议体系结构
    文件和目录的访问控制(4) 审核规则
    强名称(2)引用强名称签名的程序集
  • 原文地址:https://www.cnblogs.com/mayou18/p/6768193.html
Copyright © 2020-2023  润新知