布隆过滤器(Bloom Filter)的原理和实现

布隆过滤器使用场景

之前在《数学之美》里面看到过布隆过滤器的介绍。那么什么场景下面需要使用布隆过滤器呢?

看下下面几个问题

  • 字处理软件中,需要检查一个英语单词是否拼写正确
  • 在 FBI,一个嫌疑人的名字是否已经在嫌疑名单上
  • 在网络爬虫里,一个网址是否被访问过
  • yahoo, gmail等邮箱垃圾邮件过滤功能

以上这些场景有个共同的问题:如何查看一个东西是否在有大量数据的池子里面。

通常的做法有如下几种思路:

  • 数组
  • 链表
  • 树、平衡二叉树、Trie
  • Map (红黑树)
  • 哈希表

哈希函数

哈希函数的概念是:将任意大小的数据转换成特定大小的数据的函数,转换后的数据称为哈希值或哈希编码。下面是一幅示意图

 

可以明显的看到,原始数据经过哈希函数的映射后称为了一个个的哈希编码,数据得到压缩。哈希函数是实现哈希表和布隆过滤器的基础。

布隆过滤器介绍

  • 巴顿.布隆于一九七零年提出
  • 一个很长的二进制向量 (位数组)
  • 一系列随机函数 (哈希)
  • 空间效率和查询效率高
  • 不会漏判,但是有一定的误判率(哈希表是精确匹配)

布隆过滤器原理

布隆过滤器(Bloom Filter)的核心实现是一个超大的位数组和几个哈希函数。假设位数组的长度为m,哈希函数的个数为k

以上图为例,具体的操作流程:假设集合里面有3个元素{x, y, z},哈希函数的个数为3。首先将位数组进行初始化,将里面每个位都设置位0。对于集合里面的每一个元素,将元素依次通过3个哈希函数进行映射,每次映射都会产生一个哈希值,这个值对应位数组上面的一个点,然后将位数组对应的位置标记为1。查询W元素是否存在集合中的时候,同样的方法将W通过哈希映射到位数组上的3个点。如果3个点的其中有一个点不为1,则可以判断该元素一定不存在集合中。反之,如果3个点都为1,则该元素可能存在集合中。注意:此处不能判断该元素是否一定存在集合中,可能存在一定的误判率。可以从图中可以看到:假设某个元素通过映射对应下标为4,5,6这3个点。虽然这3个点都为1,但是很明显这3个点是不同元素经过哈希得到的位置,因此这种情况说明元素虽然不在集合中,也可能对应的都是1,这是误判率存在的原因。

添加元素

  • 将要添加的元素给k个哈希函数
  • 得到对应于位数组上的k个位置
  • 将这k个位置设为1

查询元素

  • 将要查询的元素给k个哈希函数
  • 得到对应于位数组上的k个位置
  • 如果k个位置有一个为0,则肯定不在集合中
  • 如果k个位置全部为1,则可能在集合中简易实现

简易实现

import java.util.BitSet;/*** Created by haicheng.lhc on 18/05/2017.** @author haicheng.lhc* @date 2017/05/18*/
public class SimpleBloomFilter {private static final int DEFAULT_SIZE = 2 << 24;private static final int[] seeds = new int[] {7, 11, 13, 31, 37, 61,};private BitSet bits = new BitSet(DEFAULT_SIZE);private SimpleHash[] func = new SimpleHash[seeds.length];public static void main(String[] args) {String value = " stone2083@yahoo.cn ";SimpleBloomFilter filter = new SimpleBloomFilter();System.out.println(filter.contains(value));filter.add(value);System.out.println(filter.contains(value));}public SimpleBloomFilter() {for (int i = 0; i < seeds.length; i++) {func[i] = new SimpleHash(DEFAULT_SIZE, seeds[i]);}}public void add(String value) {for (SimpleHash f : func) {bits.set(f.hash(value), true);}}public boolean contains(String value) {if (value == null) {return false;}boolean ret = true;for (SimpleHash f : func) {ret = ret && bits.get(f.hash(value));}return ret;}public static class SimpleHash {private int cap;private int seed;public SimpleHash(int cap, int seed) {this.cap = cap;this.seed = seed;}public int hash(String value) {int result = 0;int len = value.length();for (int i = 0; i < len; i++) {result = seed * result + value.charAt(i);}return (cap - 1) & result;}}
}



 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/270002.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

硬件知识:RTMP和RTSP传统流媒体协议介绍

今天给大家分享RTMP和RTSP传统流媒体协议介绍&#xff0c;希望对大家能有所帮助&#xff01; 1、RTSP 1.1 RTSP协议介绍 RTSP &#xff08;Real-Time Stream Protocol&#xff09;由Real Networks 和 Netscape共同提出的&#xff0c;基于文本的多媒体播放控制协议。RTSP定义…

常见Java面试题

一、Java基础 1、Arrays.sort实现原理和Collections.sort实现原理 答&#xff1a;Collections.sort方法底层会调用Arrays.sort方法&#xff0c;底层实现都是TimeSort实现的。TimSort算法就是找到已经排好序数据的子序列&#xff0c;然后对剩余部分排序&#xff0c;然后合并起…

电脑知识:台式电脑应该选择品牌和组装,值得收藏

互联网时代的发展&#xff0c;电脑对大家日常办公、游戏、影音娱乐都是常用的设备。今天主要给大家分享一下购买台式电脑应该注重品牌还是组装&#xff0c;相信看完本文对你选购台式电脑提供更多的参考。 1、品牌电脑 品牌电脑就是由大品牌电脑厂商&#xff08;联想、IBM、戴…

Atitit it行业图像处理行业软件行业感到到迷茫的三大原因和解决方案

Atitit it行业图像处理行业软件行业感到到迷茫的三大原因和解决方案 1. 迷茫的原因最大原因是未知1 1.1. 我在哪里&#xff1f;&#xff1f;自己的定位&#xff0c;1 1.2. 正确方向是什么&#xff1f;&#xff1f;1 1.3. 虽然找到方向&#xff0c;但前面一片迷雾&#xff0c;迷…

Docker基础:Docker是什么,为什么这么火

一、Docker是什么&#xff1f; Docker是一个开源的应用容器引擎&#xff0c;它基于go语言开发&#xff0c;并遵从Apache2.0开源协议。使用Docker可以让开发者封装他们的应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任意的 Linux 机器上运行。Docker 的核心思想打…

信息系统 项目十大管理和五大过程

PMBOK五大过程组是什么&#xff1f; PMBOK五大过程组是&#xff1a;启动过程、规划过程、执行过程、监控过程、收尾过程。 各用一句话概括项目管理知识体系五大过程组&#xff1a; 1、启动过程组&#xff1a;作用是设定项目目标&#xff0c;让项目团队有事可做&#xff1b; 2、…

查看端口占用

//进入 c:\WINDOWS\system32\ 目录 cd c:\WINDOWS\system32\ // 键入命令 netstat -ano // 查看指定端口占用情况 netstat -aon|findstr "9050"转载于:https://www.cnblogs.com/lpt1229/p/6408008.html

Docker基础:Docker安装及镜像加速配置

今天给大家分享Centos7以上版本的操作系统下安装Docker。 目录 卸载旧版本docker 安装docker需要的安装包 设置镜像仓库 国内常见镜像仓库 安装docker 启动docker 运行hello-world 卸载docker&#xff08;谨慎操作&#xff09; 确认操作系统版本 #查看系统内核 uname …

高并发场景下,到底先更新缓存还是先更新数据库?

在大型系统中&#xff0c;为了减少数据库压力通常会引入缓存机制&#xff0c;一旦引入缓存又很容易造成缓存和数据库数据不一致&#xff0c;导致用户看到的是旧数据。 为了减少数据不一致的情况&#xff0c;更新缓存和数据库的机制显得尤为重要&#xff0c;接下来带领大家踩踩…

Xamarin组件包 Xamarin.ToolKit

一 简介 Xamarin.ToolKit是个人在使用xamrin.froms开发2年中&#xff0c;因实际项目需要所自定义的组件包。该组件包采用xamarin.froms方式封装&#xff0c;用户可像普通forms控件那样使用xaml语言编写UI代码。目前该组件包的成员主要&#xff1a; 1 TabbedPage.cs&#xff1a…

Docker基础:Docker运行原理笔记

目录 1、Docker底层运行原理 2、Docker执行run命令的流程 3、Docker容器的生命周期

每个工程师都应该了解的:聊聊幂等

现在这个时代大家可能最关心的就是钱了&#xff0c;那么有没有想过你银行转账给你没有一次是转多的&#xff0c;要么失败&#xff0c;要么成功&#xff0c;为什么不能失误一下多转一笔呢&#xff1f;醒醒吧年轻人&#xff0c;别做梦了&#xff0c;做银行的能那么傻x吗&#xff…

《架构之美》阅读笔记四

书中提到了ruby on rails,所以百度了下&#xff0c;介绍如下&#xff1a; 题外话&#xff1a;Ruby on rails 它是一种可以使你开发&#xff0c;部署和维护的WEB应用程序变得简单的框架&#xff0c;以简化web开发为目标&#xff0c;它简洁&#xff0c;易懂&#xff0c;框架里的配…

Docker基础:Docker 常用命令梳理

目录 1、Docker环境信息命令 2、镜像仓库命令 3、本地镜像管理命令 4、容器生命周期管理命令

Docker基础:Docker可视化面板portainer介绍

今天给大家分享Docker可视化面板portainer工具介绍,希望对大家能有所帮助! 1、什么是portainer? Portainer是Docker的图形化管理WEB工具,由GO语言编写的,提供状态显示、应用模板快速部署、对于Docker(容器、镜像、网络、数据卷)的基本操作、日志显示、容器控制台等功能。…

时间复杂度与O(1), O(n), O(logn), O(nlogn) 的区别

在描述算法复杂度时&#xff0c;经常用到O ( 1 ) , O ( n ) , O ( l o g n ) , O ( n l o g n ) O(1), O(n), O(logn), O(nlogn)O(1),O(n),O(logn),O(nlogn)来表示对应复杂度程度, 不过目前大家默认也通过这几个方式表示空间复杂度 。 那么&#xff0c;O ( 1 ) , O ( n ) , O …

Win10技巧:Win10任务管理器知识介绍

Win10操作系统的任务管理器应该是大家比较熟悉的软件&#xff0c;尤其是在你的电脑卡掉的时候&#xff0c;不得不打开任务管理器&#xff0c;结束掉进程卡死的进程&#xff0c;然后电脑就可以恢复正常使用&#xff0c;任务管理器作为Windows操作系统上一款使用频率非常高的软件…

git保护--git分支创建

因为机缘巧合&#xff0c;我接手了一个项目&#xff0c;阴差阳错的&#xff0c;我竟然又成了这个项目的半个负责人。而这个项目呢&#xff0c;由我们团队和别的团队一起合作&#xff0c;这就遇到一个问题了&#xff0c;我们的核心技术在上传到项目中的时候就会暴露给别的团队了…

什么是局部性原理?

什么是局部性原理&#xff1f; 局部性原理的逻辑是这样的&#xff1a; 内存读写块&#xff0c;磁盘读写慢&#xff0c;而且慢很多&#xff1b; 磁盘预读&#xff1a;磁盘读写并不是按需读取&#xff0c;而是按页预读&#xff0c;一次会读一页的数据&#xff0c;每次加载更多的…