JAVA中BitSet使用

【java基础】BitSet基本说明和使用 Java平台的BitSet类用于存储一个位序列(它不是数学上的集,如果称为位向量或位数组可能更为合适)。如果需要高效地存储位序列(例如,标志),就可以使用位集。由于位集将位包装在字节里,所以使用位集要比使用Boolean对象的ArrayList高效得多。说人话就是使用位来存储boolean信息,0表示假,1表示真。BitSet由于使用bit位来存储信息,所以占用空间会比boolean数组使用空间更小,并且带有去重功能。该数据结构的一个应用就是10亿个手机号码去重(面试造火箭) 阅读详情

JAVA中BitSet

 

    JAVA中BitSet就是“位图”数据结构,根据“位图”的语义,数据的存在性可以使用bit位上的1或0来表示;一个bit具有2个值:0和1,正好可以用来表示false和true。对于判断“数据是否存在”的场景,我们通常使用HashMap来存储,不过hashmap这个数据结构KEY和Value的保存需要消耗较多的内存,不适合保存较多的数据,即大数据场景;比如在有10亿条URL中判定一个“www.baidu.com/a”是否存在,如果我们使用常规的hashmap来保存将是不现实的,因为URL本身需要占据较多的内存而无法直接操作。如果我们使用bitset来保存,那么可以对一条URL求hashcode,并将数字映射在bitset上,那么事实上它只需要bitset上的一个bit位即可,即我们1位空间即可表达一个URL字符串的存在性。

 

    所谓“存在性”,就是通过BitSet来检测一个数字是否存在。

 

1、BitSet原理

    JAVA中,一个long型数字占用64位空间,根据上述“位图”的概念,那么一个long型数字(4个字节)就可以保存64个数字的“存在性”状态(无碰撞冲突时,即true、false状态)。比如50个数字{0,1,10,...63},判定“15”是否存在,那么我们通常会首先将这些数字使用数组或者hashmap保存,然后再去判定,那么保存这些这些数据需要占用64 * 64位;如果使用位图,那么一个long型数字即可。(如果换成50个字符串,那么其节约的空间可能更大)。

 

    1) BitSet只面向数字比较,比如set(int a,boolean value)方法,将数字a在bitSet中设定为true或者false;此后可以通过get(int a)方法检测结果。对于string类型的数据,如果像使用BitSet,那么可以将其hashcode值映射在bitset中。

    2) 首先我们需要知道:1,1<<64,1<<128,1<<192...等,这些数字的计算结果是相等的(位运算);这也是一个long数字,只能表达连续的(或者无冲突的)64个数字的状态,即如果把数字1在long中用位表示,那么数字64将无法通过同一个long数字中位表示--冲突;BitSet内部,是一个long[]数组,数组的大小由bitSet接收的最大数字决定,这个数组将数字分段表示[0,63],[64,127],[128,191]...。即long[0]用来存储[0,63]这个范围的数字的“存在性”,long[1]用来存储[64,127],依次轮推,这样就避免了位运算导致的冲突。

|------------|----------|----------|----------|----------|
|
|  数字范围      [0,63]     [64,127]  [128,191]     ...   |
|------------|----------|----------|----------|----------|
|
|long数组索引      0           1          2         ...   |
|------------|----------|----------|----------|----------|

 

    3) bitSet内部的long[]数组是基于向量的,即随着set的最大数字而动态扩展。数组的最大长度计算:

(maxValue - 1) >> 6  + 1

 

    4) BitSet中set方法伪代码:

public void set(int number) {
	int index = number >> 6;//找到number需要映射的数组的index。
	if(index + 1 > length) {
		ensureCapacity(index + 1);//重新扩展long[]数组
	} 
	long[index] |= (1L << number);//冲突解决
}

 

2、使用BitSet:本例中使用bitSet做String字符串的存在性校验。

BitSet bitSet = new BitSet(Integer.MAX_VALUE);//hashcode的值域

//0x7FFFFFFF
String url = "http://baidu.com/a";
int hashcode = url.hashCode() & 0x7FFFFFFF;
bitSet.set(hashcode);

System.out.println(bitSet.cardinality());//着色位的个数
System.out.println(bitSet.get(hashcode));//检测存在性
bitSet.clear(hashcode);//清除位数据

 

3、BitSet与Hashcode冲突

    因为BitSet API只能接收int型的数字,即只能判定int数字是否在bitSet中存在。所以,对于String类型,我们通常使用它的hashcode,但这有一种隐患,java中hashcode存在冲突问题,即不同的String可能得到的hashcode是一样的(即使不重写hashcode方法),如果我们不能很好的解决这个问题,那么就会出现“数据抖动”---不同的hashcode算法、运行环境、bitSet容量,会导致判断的结果有所不同。比如A、B连个字符串,它们的hashcode一样,如果A在BitSet中“着色”(值为true),那么检测B是否在BitSet存在时,也会得到true。

 

    这个问题该如何解决或者缓解呢?

    1)调整hashcode生成算法:我们可以对一个String使用多个hashcode算法,生成多个hashcode,然后在同一个BitSet进行多次“着色”,在判断存在性时,只有所有的着色位为true时,才判定成功。

String url = "http://baidu.com/a";
int hashcode1 = url.hashCode() & 0x7FFFFFFF;
bitSet.set(hashcode1);

int hashcode2 = (url + "-seed-").hashCode() & 0x7FFFFFFF;
bitSet.set(hashcode2);
System.out.println(bitSet.get(hashcode1) && bitSet.get(hashcode2));
//也可以在两个不同的bitSet上进行2次“着色”,这样冲突性更小。但会消耗双倍的内存

 

    其实我们能够看出,这种方式降低了误判的概率。但是如果BitSet中存储了较多的数字,那么互相覆盖着色,最终数据冲突的可能性会逐渐增加,最终仍然有一定概率的判断失误。所以在hashcode算法的个数与实际String的个数之间有一个权衡,我们建议:  “hashcode算法个数 * String字符串的个数”  < Integer.MAX_VALUE * 0.8

 

    2) 多个BitSet并行保存:

    改良1)中的实现方式,我们仍然使用多个hashcode生成算法,但是每个算法生成的值在不同的BitSet中着色,这样可以保持每个BitSet的稀疏度(降低冲突的几率)。在实际结果上,比1)的误判率更低,但是它需要额外的占用更多的内存,毕竟每个BitSet都需要占用内存。这种方式,通常是缩小hashcode的值域,避免内存过度消耗。

BitSet bitSet1 = new BitSet(Integer.MAX_VALUE);//127M
BitSet bitSet2 = new BitSet(Integer.MAX_VALUE);

String url = "http://baidu.com/a";
int hashcode1 = url.hashCode() & 0x7FFFFFFF;
bitSet1.set(hashcode1);

int hashcode2 = (url + "-seed-").hashCode() & 0x7FFFFFFF;
bitSet2.set(hashcode2);

System.out.println(bitSet1.get(hashcode1) && bitSet2.get(hashcode2));

 

    3) 是否有必要完全避免误判?

    如果做到100%的正确判断率,在原理上说BitSet是无法做的,BitSet能够保证“如果判定结果为false,那么数据一定是不存在;但是如果结果为true,可能数据存在,也可能不存在(冲突覆盖)”,即“false == YES,true == Maybe”。有人提出将冲突的数据保存在类似于BTree的额外数据结构中,事实上这种方式增加了设计的复杂度,而且最终仍然没有良好的解决内存占用较大的问题。

 

4、BloomFilter(布隆姆过滤器)

    BloomFilter 的设计思想和BitSet有较大的相似性,目的也一致,它的核心思想也是使用多个Hash算法在一个“位图”结构上着色,最终提高“存在性”判断的效率。请参见Guava  BloomFilter。如下为代码样例:

Charset charset = Charset.forName("utf-8");
BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(charset),2<<21);//指定bloomFilter的容量
String url = "www.baidu.com/a";
bloomFilter.put(url);
System.out.println(bloomFilter.mightContain(url));

  

5、内存消耗

    据上所述,BitSet可以有效的降低内存的使用量,但是它的内存使用量是有内部long数组的大小决定,所以在创建BitSet时指定的值域非常重要,过大的值域将会导致OOM(比如指定Long.MAX_VALUE),在一个BitMap上存储Integer.MAX_VALUE个“着色”(注意,BitSet只能对正数操作),大概消耗128M内存。

【Java】BitSet的使用 阅读详情

相关推荐

【微信小程序开发与设计】垃圾智能分类小程序

垃圾分类是将来生活可持续发展的必需项。但是很多人由于缺乏垃圾分类知识,或是因为垃圾分类困难,费时费力,所以没有好好贯彻垃圾分类政策,此时设计一款方便于群众进行智能化垃圾识别分类的微信小程序就显得尤为必要。

Markelle_Fultz的博客 8246

java中的BitSet学习

(1)BitSet类     大小可动态改变, 取值为true或false的位集合。用于表示一组布尔标志。    此类实现了一个按需增长的位向量。位 set 的每个组件都有一个 boolean 值。用非负的整数将 BitSet 的位编入索引。可以对每个编入索引的位进行测试、设置或者清除。通过逻辑与、逻辑或和逻辑异或操作,可以使用一个 BitSet 修改另一个 BitSet 的内容。

2万+

Fabric学习笔记(一)- Centos 7下的Fabric 2.3.2环境搭建

一、 环境准备 (一)、在VMware Workstation 15 安装一个Centos 7的虚拟环境,切换到图形化界面: 参考文章链接:Centos 7切换图形化界面 其中可能在yum groupinstall "X Window System"时会报错:Cannot find a valid baseurl for repo: base/7/x86_6,参考这篇文章即可:安装图形化界面报错解决 (二)、打开终端,安装所需的库: 切换root用户,输入命令:su root yum更新,输入命令:y

茕夜 2611

Java中BitSet的使用及详解

BitSet是一个非常强大的工具,适用于需要高效管理和操作大量布尔值的场景。通过使用BitSet,可以显著减少内存使用,并提高程序的执行效率.它在数据库索引、权限管理、状态标记等方面有着广泛的应用。版权声明:本博客内容为原创,转载请保留原文链接及作者信息。参考文章学会使用BitSet浅谈Java BitSet使用场景和代码示例。

ning的博客 1697

matlab中高频变压器怎么找,干货|手把手教你绕制高频变压器

原标题:干货|手把手教你绕制高频变压器绕制一个变压器所需材料:磁芯、骨架、各种铜线、麦拉胶带。变压器参数:磁芯:EE22原边:134T(1-3脚),辅助:32T(5-4脚),输出:15T(10-9脚)原边电感:1380±10%uH漏感:≤44uH引脚分布图: 特别注意:绕制方法为网上下载,其中变压器绕制方法是对的,但其中存在着很多问题(比如,正规变压器的绕组的头和尾是要添加铁氟龙套管的,每一层之间...

weixin_30895121的博客 2125

谈谈 FOC和BLDC 电机控制

更具体地说,通过 “Park 变换”,我们可以把三相交流电流信号转换成两相直流电流信号,从而可以把三相交流电机的控制变得和两相直流电机控制一样简单。在内环 “电流环”中,一些比较重要的模块有 “Clark 变换” 和 “Park 变换” 等数学模块、电机电流信号检测模块以及能够提供电机的转速和转角位置信息的模块。日前,Qorvo 电机控制应用高级系统/应用工程师张绍发表了一个与 BLDC 和 FOC 相关的演讲,科普了 FOC 的相关知识,还讲解了 Qorvo 用于简化 FOC 实施方案的方法。

U_YAO的博客 2118

Java 中 BitSet 类的用法

注:获取的区间后,索引的编号会改变,比如这里新的 BitSet 的 0 号索引对应的是原来 BitSet 的 4 号索引。有三个和长度相关的 API,分别是 size、cardinal、length。

yaoyaoxuanxuan1的博客 1153

树莓派Bookworm系统避坑指南:3种方法解决pip install报错externally-managed-environment

本文详细解析树莓派Bookworm系统中pip install报错externally-managed-environment的成因,并提供三种实用解决方案:使用虚拟环境(venv)隔离项目依赖、通过pipx管理全局Python工具,以及理解风险后的系统安装方法。帮助开发者安全高效地管理Python环境,避免系统冲突。

android的专栏 764

Java 中 BitSet

Java 中 BitSet 就是“位图”数据结构,根据“位图”的语义,数据的存在性可以使用 bit 位上的1或0来表示;一个 bit 具有2个值:0和1,正好可以用来表示 false 和 true。对于判断“数据是否存在”的场景,我们通常使用 HashMap 来存储,不过 hashmap 这个数据结构 Key 和 Value 的保存需要消耗较多的内存,不适合保存较多的数据,即大数据场景

zhangxin09的专栏 8293

【OpenClaw企业级智能体实战】第32篇:政企版OpenClaw安全落地指南——奇安信55页报告深度拆解与实战

2026年Q2,OpenClaw(俗称“龙虾”)安全风险集中爆发,公安部、工信部等监管机构密集发声,23万公网暴露实例、155个高危漏洞让企业“养虾”安全压力骤增。奇安信发布的55页《政企版龙虾安全使用指南》,以“看得清、管得住、用得好”为核心,构建了“端-网-云”三层防护体系。本文深度拆解这份报告的九大安全面与三大趋势,全景扫描奇安信、腾讯、360等头部厂商安全方案,提炼企业最低安全基线与实操配置,通过金融机构虚拟案例演示落地全流程,提供从资产摸底、规范制定到工具部署的完整解决方案。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 572

Qt —— 调用海康C++版SDK获取摄像头每帧图像,通过OpenCv处理每帧图像后显示在Qt窗口(附:源码)

  关注 笔者 - jxd 微信公众号搜索 “码农总动员” 或 微信扫描下方二维码,了解更多你不知道的XX,O(∩_∩)O

5447

Java BitSet使用场景和示例

阅读目录一、什么是BitSet?二、Java BitSet实现原理三、使用场景四、参考资料 回到顶部一、什么是BitSet?   注:以下内容来自JDK API:   BitSet类实现了一个按需增长的位向量。位Set的每一个组件都有一个boolean值。用非负的整数将BitSet的位编入索引。可以对每个编入索引的位进行测试、设置或者清除。通过逻辑与、逻辑或和逻辑异或操作,可以使用一个 BitSet修改另一个 BitSet的内容。    默认情况下,set 中所有位的初始值都是false。

灼烧的疯狂 495

【AI测试干货】软件测试 - 全流程提示词完整体系

本篇教程是一套专为软件测试工程师打造的 AI 协作提示词体系。从测试计划制定、用例设计、自动化脚本开发、缺陷管理,到测试报告生成,每个环节都提供了结构化的提示词模板,帮助测试人员高效利用 AI 提升工作质量。

blues_C的博客 348

java bitset_Java BitSet or()方法与示例

java bitset BitSet类或()方法 (BitSet Class or() method) or() method is available in java.util package. or()方法在java.util包中可用。 or() method is used to perform logical OR between this BitSet and the given Bit...

cumt951045的博客 771

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

java BitSet原理解析

       学习了Java BitSet之后,写下这篇博文记录一下BetSet的原理及使用场景。 一、BitSet原理        BitSet,通过这个名字字面意思(位集合),就可以知道,它的使用应该与位(Bit)有关。事实也确实如此,它(BitSet)用于标志一个“东西”是否存在于这个“东西”的一个集合里面。这句话很拗口,举实例来说明,比如:一个字符是否存在一个字符串中。一个数字是否存...

林序的博客 2117

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

java bitset_Java BitSet cardinality()方法与示例

java bitset BitSet类cardinality()方法 (BitSet Class cardinality() method) cardinality() method is available in java.util package.cardinality()方法在java.util包中可用。 cardinality() method is used to return the ...

cumtb2002的博客 867

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

JAVA Bitset应用总结

/** * 演示java.util.BitSet类的使用 * BitSet类表示自动增长位集合 * @author Sking */ package bitset; import java.util.BitSet; public class BitSetAPITest { public static void main(String[] args){ //BitSet的构造函数

别忘了初衷 2882

Java BitSet

适用于操作整型数据。每个数据由一位bit表示,也就是说每一个整型只需一个bit的控件,这个比collection等容器是有天大的优势啊。而且插入和查询都非常方便,因为bit的index和整型数值相等,如:存储127,那么BitSet中的第127位bit就被置为1。查找127是否在BitSet中,只需使用MASK进行与操作即可。 但是可以想象到,BitSet中至少需要有多少位bit,决定于存储在B...

淡淡的宁静的博客 1247

java中BitSet详解

该类在java的java.util包中。 BitSet类的原理主要是利用long型有64个bit,每个bit存储一个数值,这样一个long型数字就能存储64个数字,进而节省了空间。接下来我们开始讲解该类的代码。 我们先看一下该类的成员变量: /* * BitSets are packed into arrays of "words." Currently a word is ...

weixin_39935887的博客 3928

java bitset_Java BitSet xor()方法与示例

java bitset BitSet类xor()方法 (BitSet Class xor() method) xor() method is available in java.util package. xor()方法在java.util包中可用。 xor() method is used to perform logical XOR between this BitSet and the gi...

cumtb2009的博客 459

java bitset xor_java中的BitSet

(1)BitSet类大小可动态改变, 取值为true或false的位集合。用于表示一组布尔标志。此类实现了一个按需增长的位向量。位 set 的每个组件都有一个 boolean 值。用非负的整数将 BitSet的位编入索引。可以对每个编入索引的位进行测试、设置或者清除。通过逻辑与、逻辑或和逻辑异或操作,可以使用一个 BitSet 修改另一个BitSet 的内容。默认情况下,set 中所有位的初始值都...

weixin_29980355的博客 200

java bitset javadoc_转载–Java中 BitSet的一些了解

目前,看起来在网上对BitSet的一些东东也只有下面的一些了解了。 其实这个类的一些东西在其JavaDoc中,还是很明白的。很多人都不知道BitSet类,学习java 不知道这个类是多么难看的事啊. BitSet实际是由“二进制位”构成的一个Vector。如果希望高效率地保存大量“开-关”信息,就应使用BitSet。它只有从尺寸的角度看才有意义;如果希望的高效率的访问,那么它的速度会比使用一些固有...

weixin_35626408的博客 200

Java bitset转string_Java中BitSet使用(转)

packageutil;importjava.util.Arrays;importjava.util.BitSet;public classBitSetDemo {/*** 求一个字符串包含的char**/public static voidcontainChars(String str) {BitSet used= newBitSet();for (int i = 0; i < str.l...

weixin_39756192的博客 501

Java基础:JAVA中BitSet使用详解

适用场景 整数,无重复 Bitset 基础 Bitset,也就是位图,由于可以用非常紧凑的格式来表示给定范围的连续数据而经常出现在各种算法设计中。上面的图来自c++库中bitset的一张图。 基本原理是,用1位来表示一个数据是否出现过,0为没有出现过,1表示出现过。使用用的时候既可根据某一个是否为0表示此数是否出现过。 一个1G的空间,有 8102410241024=8.5810^9bit,也就...

TuT 8361
上一篇: guava cache与编程实践
下一篇: Mongodb与GridFS
shift_alt_ctrl
博客等级 码龄10年 0粉丝 83原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值