用BitMap结构实现快速取差集

2024-01-31 06:12

本文主要是介绍用BitMap结构实现快速取差集,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在流式计算对比基线无数据告警场景中,利用基线数据对比来源数据,如果发现该时间窗口内的数据不在基线数据中则产生告警,因此基线数据和来源数据需要进行对比计算,基线数据去掉来源数据中已有的数据,余下的数据作为产生的告警数据。在数据量较小时直接进行集合运算取差集即可,但是但基线数据和来源数据量达百万甚至千万时则计算缓慢,出现延时,因此需要找到其它方式方法。

基线数据的定义:
基线数据是一组带时分的时序数据,时分是根据配置对24小时进行分割得到,比如配置1分钟内没数据则告警,则24小时按1分钟进行分割,则分割成00:01, 00:02…的时序数据,总共1440条记录,1440条表示每个1分钟窗口内有一条数据。配置5分钟内没数据则告警,则按5分钟进行分割,则分割成00:05, 00:10…的时序数据,每个时间窗口内有且仅有一条数据。每个任务对应一组基线数据。

假设基线数据量为一百万条,窗口内来源数据为九十九万九千条,基线数据中移除来源数据即取差集后则只有一千条。

2.1 集合的取差集方法
1)List.removeAll(sublist)方法取差集

private static void testRemoveAll() {List<String> listA = new ArrayList<>();for(int i=0;i<OneMillion;i++){ //随机创建百万条基线数据String key1="ip(192.168.199.10"+i+")#port("+i+")#service_name(orcl)#time(23:30:00)"+i;listA.add(key1);}//从百万条基线数据中随机获取九十九万九千条作为来源数据List<String> listB = createRandomList(listA,999000);Date date = new Date();listA.removeAll(listB);Date date1 = new Date();System.out.println("testRemoveAll:"+(date1.getTime()-date.getTime())/1000+"秒");System.out.println(listA.size());
}

测试结果:
30分钟未计算出结果,手动kill程序。

2)List.removeAll(new HashSet(sublist))方法取差集
分析removeAll方法的源码,发现removeAll方法中有subList.contain(value)的方法,如果subList为list集合,则调用indexOf()方法,一个一个地遍历查找。最坏时间复杂度为O(总数据量)。如果先将subList转为HashSet,在调用contain方法时,则时间复杂度为O(1),加快对比计算速度。

private static void testRemoveAll() {List<String> listA = new ArrayList<>();for(int i=0;i<OneMillion;i++){ //随机创建百万条基线数据String key1="ip(192.168.xxx.10"+i+")#port("+i+")#service_name(orcl)#time(23:30:00)"+i;listA.add(key1);}//从百万条基线数据中随机获取九十九万九千条作为来源数据List<String> listB = createRandomList(listA,999000);Date date = new Date();//listA.removeAll(listB);listA.removeAll(new HashSet(listB));Date date1 = new Date();System.out.println("testRemoveAll:"+(date1.getTime()-date.getTime())/1000+"秒");System.out.println(listA.size());
}
//0.3秒

测试结果:
计算耗时仅0.3s,这个结果相比上一步有巨大提升。

2.2 BitMap的取差集方法
BitMap,直译为位图,是一种数据结构,代表了有限域中的稠集(Dense Set),每一个元素至少出现一次,没有其他的数据和元素相关联。在索引,数据压缩等方面有广泛应用。
计算机中1 byte = 8 bit,一个比特(bit,称为比特或者位)可以表示1或者0两种值,通过一个比特去标记某个元素的值,而KEY或者INDEX就是该元素,构成一张映射关系图。因为采用了Bit作为底层存储数据的单位,所以可以极大地节省存储空间。同时还支持去重,交集,差集等各种运算Bitmap的实现有很多,例如Java原生的BitSet,第三方的RoaingBitmap等。

1)Java原生的BitSet

private static void testBitSet() {List<String> listA = new ArrayList<>();BitSet bitmap = new BitSet();for(int i=0;i<OneMillion;i++){String key1="ip(192.168.XXX.10"+i+")#port("+i+")#service_name(orcl)#time(23:30:00)"+i;bitmap.set(Math.abs(key1.hashCode()));listA.add(key1);}BitSet bitmap1 = new BitSet();List<String> listB = createRandomList(listA,999000);for(String s:listB){bitmap1.set(Math.abs(s.hashCode()));}Date date = new Date();bitmap.andNot(bitmap1);Date date1 = new Date();System.out.println("testBitSet:"+(double)(date1.getTime()-date.getTime())/1000+"秒");
}
//testBitSet:0.02秒

测试结果:
计算耗时仅0.02s,这个结果相比上一步时间缩短一个数量级。
2)RoaingBitmap
Bitmap的主要缺陷是占用大量的内存空间。Bitmap是一种使用位图来表示数据集合的数据结构,每个位代表一个元素的存在与否。当数据集合很大时,Bitmap需要使用大量的位来表示,导致内存占用较高。
RoaringBitmap是一种改进的Bitmap数据结构,它能够解决Bitmap的内存占用问题。RoaringBitmap使用了一种压缩算法,能够有效地压缩位图数据,减少内存占用。具体来说,RoaringBitmap将位图分成多个块,每个块使用不同的压缩算法进行压缩。这样,当数据集合中存在大量连续的元素时,RoaringBitmap能够更好地压缩数据,减少内存占用。另外,RoaringBitmap还支持快速的位图操作,如并集、交集和差集等,使得对数据集合的操作更加高效。RoaringBitmap还支持动态增长,可以动态地添加和删除元素,而不需要重新分配内存。
总的来说,RoaringBitmap通过压缩算法和优化的位图操作,能够有效地解决Bitmap的内存占用问题,提高了位图数据结构的性能和可扩展性。

private static void testRoaringBitmap() {List<String> listA = new ArrayList<>();RoaringBitmap bitmap = new RoaringBitmap();for(int i=0;i<OneMillion;i++){String key1="ip(192.168.xxx.10"+i+")#port("+i+")#service_name(orcl)#time(23:30:00)"+i;bitmap.add(Math.abs(key1.hashCode()));listA.add(key1);}RoaringBitmap bitmap1 = new RoaringBitmap();List<String> listB = createRandomList(listA,999000);for(String s:listB){bitmap1.add(Math.abs(s.hashCode()));}Date date = new Date();bitmap.andNot(bitmap1);Date date1 = new Date();System.out.println("testRoaringBitmap:"+(double)(date1.getTime()-date.getTime())/1000+"秒");
}
//testRoaringBitmap:0.022秒

测试结果:
计算耗时仅0.022s,这个结果和Java原生的BitSet时间基本相同。
总 结:
通过上述测试对比,相比其它方式采用BitMap和升级的RoaingBitmap在时间上能缩小一个数量级,效果十分明显,但是使用BitMap和RoaingBitmap存在的问题是BitMap结构只支持数字,如果是字符串需要先将字符串转成数字,字符串转数字时有一定的概率出现hash碰撞(不同的字符串转成相同的数字),因此如果能允许一定的误差,用Bitmap和RoaingBitmap是最快的。

这篇关于用BitMap结构实现快速取差集的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/662801

相关文章

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

hdu 4565 推倒公式+矩阵快速幂

题意 求下式的值: Sn=⌈ (a+b√)n⌉%m S_n = \lceil\ (a + \sqrt{b}) ^ n \rceil\% m 其中: 0<a,m<215 0< a, m < 2^{15} 0<b,n<231 0 < b, n < 2^{31} (a−1)2<b<a2 (a-1)^2< b < a^2 解析 令: An=(a+b√)n A_n = (a +