Java BitSet使用场景和示例

一、什么是BitSet?

  注:以下内容来自JDK API:

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

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

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

回到顶部

Java BitSet API简介

BitSet()
          创建一个新的位 set。

BitSet(int nbits)
          创建一个位 set,它的初始大小足以显式表示索引范围在 0 到 nbits-1 的位。

 

void

and(BitSet set)
          对此目标位 set 和参数位 set 执行逻辑操作。

void

andNot(BitSet set)
          清除此 BitSet 中所有的位,其相应的位在指定的 BitSet 中已设置。

int

cardinality()
          返回此 BitSet 中设置为 true 的位数。

void

clear()
          将此 BitSet 中的所有位设置为 false

void

clear(int bitIndex)
          将索引指定处的位设置为 false

void

clear(int fromIndex, int toIndex)
          将指定的 fromIndex(包括)到指定的 toIndex(不包括)范围内的位设置为 false

Object

clone()
          复制此 BitSet,生成一个与之相等的新 BitSet

boolean

equals(Object obj)
          将此对象与指定的对象进行比较。

void

flip(int bitIndex)
          将指定索引处的位设置为其当前值的补码。

void

flip(int fromIndex, int toIndex)
          将指定的 fromIndex(包括)到指定的 toIndex(不包括)范围内的每个位设置为其当前值的补码。

boolean

get(int bitIndex)
          返回指定索引处的位值。

BitSet

get(int fromIndex, int toIndex)
          返回一个新的 BitSet,它由此 BitSet 中从 fromIndex(包括)到 toIndex(不包括)范围内的位组成。

int

hashCode()
          返回此位 set 的哈希码值。

boolean

intersects(BitSet set)
          如果指定的 BitSet 中有设置为 true 的位,并且在此 BitSet 中也将其设置为true,则返回 ture。

boolean

isEmpty()
          如果此 BitSet 中没有包含任何设置为 true 的位,则返回 ture。

int

length()
          返回此 BitSet 的“逻辑大小”:BitSet 中最高设置位的索引加 1。

int

nextClearBit(int fromIndex)
          返回第一个设置为 false 的位的索引,这发生在指定的起始索引或之后的索引上。

int

nextSetBit(int fromIndex)
          返回第一个设置为 true 的位的索引,这发生在指定的起始索引或之后的索引上。

void

or(BitSet set)
          对此位 set 和位 set 参数执行逻辑操作。

void

set(int bitIndex)
          将指定索引处的位设置为 true

void

set(int bitIndex, boolean value)
          将指定索引处的位设置为指定的值。

void

set(int fromIndex, int toIndex)
          将指定的 fromIndex(包括)到指定的 toIndex(不包括)范围内的位设置为 true

void

set(int fromIndex, int toIndex, boolean value)
          将指定的 fromIndex(包括)到指定的 toIndex(不包括)范围内的位设置为指定的值。

int

size()
          返回此 BitSet 表示位值时实际使用空间的位数。

String

toString()
          返回此位 set 的字符串表示形式。

void

xor(BitSet set)
          对此位 set 和位 set 参数执行逻辑异或操作。

二、Java BitSet实现原理

  在java中,BitSet的实现位于java.util包中:

复制代码

public class BitSet implements Cloneable, java.io.Serializable 
{
    private final static int ADDRESS_BITS_PER_WORD = 6;
    private final static int BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;
    private final static int BIT_INDEX_MASK = BITS_PER_WORD - 1;

    /* Used to shift left or right for a partial word mask */
    private static final long WORD_MASK = 0xffffffffffffffffL;

    private static final ObjectStreamField[] serialPersistentFields =
     {
        new ObjectStreamField("bits", long[].class),
    };

    /**
     * The internal field corresponding to the serialField "bits".
     */
    private long[] words;
    
    .....
}

复制代码

  可以看到,BitSet的底层实现是使用long数组作为内部存储结构的,所以BitSet的大小为long类型大小(64位)的整数倍。

  它有两个构造函数:

  1、BitSet():创建一个新的位 set,默认大小是64位。

 public BitSet() 
{
        initWords(BITS_PER_WORD);
        sizeIsSticky = false;
}

  2、BitSet(int nbits):创建一个位set,它的初始大小足以显式表示索引范围在 0 到 nbits-1 的位。

复制代码

    public BitSet(int nbits)
     {
        // nbits can't be negative; size 0 is OK
        if (nbits < 0)
            throw new NegativeArraySizeException("nbits < 0: " + nbits);
        initWords(nbits);
        sizeIsSticky = true;
    }

复制代码

  注:

  1、如果指定了bitset的初始化大小,那么会把他规整到一个大于或者等于这个数字的64的整倍数。比如64位,bitset的大小是1个long,而65位时,bitset大小是2个long,即128位。做这么一个规定,主要是为了内存对齐,同时避免考虑到不要处理特殊情况,简化程序。

  2:BitSet的size方法:返回此 BitSet 表示位值时实际使用空间的位数,值是64的整数倍

   length方法:返回此 BitSet 的“逻辑大小”:BitSet 中最高设置位的索引加 1  

回到顶部

三、使用场景

   常见的应用场景是对海量数据进行一些统计工作,比如日志分析、用户数统计等。

  之前在阿里的实习面试就被问到一道题:有1千万个随机数,随机数的范围在1到1亿之间。现在要求写出一种算法,将1到1亿之间没有在随机数中的数求出来?

  代码示例如下: 

复制代码

public class Alibaba
{
    public static void main(String[] args)
    {
        Random random=new Random();
        
        List<Integer> list=new ArrayList<>();
        for(int i=0;i<10000000;i++)
        {
            int randomResult=random.nextInt(100000000);
            list.add(randomResult);
        }
        System.out.println("产生的随机数有");
        for(int i=0;i<list.size();i++)
        {
            System.out.println(list.get(i));
        }
        BitSet bitSet=new BitSet(100000000);
        for(int i=0;i<10000000;i++)
        {
            bitSet.set(list.get(i));
        }
        
        System.out.println("0~1亿不在上述随机数中有"+bitSet.size());
        for (int i = 0; i < 100000000; i++)
        {
            if(!bitSet.get(i))
            {
                System.out.println(i);
            }
        }     
    }
}

复制代码

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值