首页 > 其他分享 >面试官:如何实现10亿数据判重?

面试官:如何实现10亿数据判重?

时间:2024-03-28 22:29:36浏览次数:16  
标签:10 面试官 判重 元素 bitmap BitSet 数据量 BitMap

当数据量比较大时,使用常规的方式来判重就不行了。

例如,使用 MySQL 数据库判重,或使用 List.contains() 或 Set.contains() 判重就不可行,因为 MySQL 在数据量大时查询就会非常慢,而数据库又是及其珍贵的全局数据库资源。

《阿里巴巴Java开发手册》上也说了,如果单表数据量超过 500 万或 2GB 时就建议分库分表了,如下图所示:

图片

所以数据库去重显然是不行的。而使用集合也是不合适的,因为数据量太大,使用集合会导致内存不够用或内存溢出和 Full GC 频繁等问题,所以此时我们的解决方案通常是采用布隆过滤器来实现判重。

知识扩展

除了布隆过滤器之外,我们还可以使用 BitMap(位图)的数据类型来实现判重。

位图(BitMap)是一种数据结构,用于表示一个特定范围内的元素是否存在或者某种状态,通常用二进制位来表示。在位图中,每一个位只能是 0 或 1,分别表示元素不存在或存在。位图通常用一个 bit 数组来实现,每个 bit 位对应一个元素,如下图所示:

图片

其中,上图中的 1 表示有值,上面 BitMap 描述的值是 1,3,5。

BitMap 优点分析

位图的优势包括:

  1. 空间效率优势:位图极大地节省了存储空间。对于大量稀疏数据,特别是当元素数量远大于实际存在的项时,相比于使用传统的列表、集合等数据结构,位图占用的空间极小。
  2. 查询速度:由于内存访问是按字节或字进行的,因此对单个元素的存在性检查时间复杂度为 O(1),即常量时间,非常快速。
  3. 批量操作高效:对于批量插入、删除和查询操作,尤其是统计某一范围内元素的数量,位图表现出优秀的性能。

BitMap VS int

以 Java 中的 int 为例,来对比观察 BitMap 的优势,在 Java 中,int 类型通常需要 32 位(4 字节*8),而 BitMap 使用 1 位就可以来标识此元素是否存在,所以可以认为 BitMap 占用的空间大小,只有 int 类型的 1/32,所以有大数据量判重时,使用 BitMap 也可以实现。

PS:布隆过滤器的底层就是基于 BitMap 数据结构实现的。

BitMap 在 Java 中的使用

BitMap 在 Java 中的具体实现是 java.util 中的 BitSet,BitSet 是一个可变大小的位向量,能够动态增长以容纳更多的位数据,以下是 BitSet 基本使用示例:

import java.util.BitSet;

public class BitmapExample {
    public static void main(String[] args) {
        // 创建一个BitSet实例
        BitSet bitmap = new BitSet();

        // 设置第5个位置为1,表示第5个元素存在
        bitmap.set(5);

        // 检查第5个位置是否已设置
        boolean exists = bitmap.get(5);
        System.out.println("Element at position 5 exists: " + exists);  // 输出: Element at position 5 exists: true

        // 设置从索引10到20的所有位置为1
        bitmap.set(10, 21);  // 参数是包含起始点和不包含终点的区间

        // 计算bitset中所有值为1的位的数量,相当于计算设置了的元素个数
        int count = bitmap.cardinality();
        System.out.println("Number of set bits: " + count);

        // 清除第5个位置
        bitmap.clear(5);

        // 判断位图是否为空
        boolean isEmpty = bitmap.isEmpty();
        System.out.println("Is the bitset empty after clearing some bits? " + isEmpty);
    }
}

课后思考

除了布隆过滤器和 BitMap 之外,还有哪些大数据量判重的实现方案呢?布隆过滤器实现判重的原理又是啥呢?

标签:10,面试官,判重,元素,bitmap,BitSet,数据量,BitMap
From: https://blog.csdn.net/qq_43842093/article/details/137126400

相关文章

  • P6105 [Ynoi2010] y-fast trie
    [Ynoi2010]y-fasttrie-洛谷这道题让我学到了一些之前看过但没总结出来的\(trick\)显然加入集合中数要先取模对于\(x+y\geqC\)的部分,直接取最大和次大即可对于\(x+y<C\)的部分,我们先考虑暴力枚举\(x\),二分找到每一个\(y\)取最优即可若此题离线,考......
  • 在window10或window11 上运行带有签名的.msix 文件。
    1)、单击有签名的.msix文件》属性》    ok,这样就可以成功安装了 ......
  • pat 1006 换个格式输出整数
    让我们用字母B来表示“百”、字母S表示“十”,用12...n来表示不为零的个位数字n(<10),换个格式来输出任一个不超过3位的正整数。例如234应该被输出为BBSSS1234,因为它有2个“百”、3个“十”、以及个位的4。输入格式:每个测试输入包含1个测试用例,给出正整数n(<......
  • P1037 [NOIP2002 普及组] 产生数 python 题解
    原题链接:产生数原理解释本题就是基本的dfs,对每一个数遍历深搜,得到他能变化的所有情况,最后相乘就是结果,网上都是c的解法,需要用到高精度,但是python可以处理大数,不需要。vis[]判断该数是否变换过,防止重复以n=123,k=2,变换列表x=[1,3],y=[3,4],即1->3,3->4:先遍历1:遍历......
  • day10:字典的循环遍历及序列操作
    一、字典的循环遍历1.遍历字典的键dict1={'name':'张三','age':20,'gender':'男'}forkeyindict1.keys():print(key)#name#age#gender2.遍历字典的值dict1={'name':'张三','age':20,'......
  • SCP简介以及106~110的介绍
    注:本文只供开玩笑 ,与 Anisolatedperson合作 目录SCP-106SCP-107SCP-108SCP-109SCP-110---------------------------------------------------------------------------------------------------------------------------------SCP-106SCP-106对象类:KeterS......
  • 代码随想录Day17 ● 110.平衡二叉树 ● 257. 二叉树的所有路径 ● 404.左叶子之和
     110.平衡二叉树 classSolution{public://返回以该节点为根节点的二叉树的高度,如果不是平衡二叉树了则返回-1intgetHeight(TreeNode*node){if(node==NULL){return0;}intleftHeight=getHeight(node->left......
  • 花了100块大洋搞懂 ipv6的用户如何访问ipv4 服务器
    大家好,今天蓝胖子花了100多块搞懂了ipv6的用户如何访问ipv4服务器,将收获与大家分享下。ipv4和ipv6的协议栈不同,这意味着,其对应的ip包的封装和解析不同,那么只支持ipv4的机器就无法直接与ipv6的服务器进行通信。但目前已经有越来越多人使用ipv6进行通信,如果仅仅让服务器支持ipv4,......
  • FPGA入门笔记010——UART串口接收模块设计
    1、串口接收模块原理​当对于数据线Rs232_Rx上的每一位进行采样时,一般情况下认为每一位数据的中间点是最稳定的。因此一般应用中,采集中间时刻时的电平即认为是此位数据的电平,如图1所示。图1——串口接收时序图(图中BPS_CLK为采样时钟)​但是在实际工业应......
  • 「CTSC2010」星际旅行
    换根dp#贪心由限制\(h_i\)大于点的度数,最终回到根的答案必然是经过每个节点的根的答案可以\(\mathcal{O}(n)\)的算出考虑如何换根,分\(3\)种情况(假设现在由\(rt\rightarrowx\))当前的\(rt\)有多余的出边,那么用这个出边走到\(x\),\(ans+1\)当前\(rt\)没有多余......