什么是布隆过滤器?如何使用?

2023-11-06

欢迎搜索


Redis缓存穿透可以通过布隆过滤器进行解决,那么什么是布隆过滤器呢?请往下看。

通常你判断某个元素是否存在用的是什么?

很多人想到的是HashMap。
确实可以将值映射到 HashMap 的 Key,然后可以在 O(1) 的时间复杂度内返回结果,效率奇高。但是 HashMap 的实现也有缺点,例如存储容量占比高,考虑到负载因子的存在,通常空间是不能被用满的,而一旦你的值很多例如上亿的时候,那 HashMap 占据的内存大小就变得很可观了。

一、布隆过滤器简介

布隆过滤器(英语:Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中

如果想判断一个元素是不是在一个集合里,一般想到的是将集合中所有元素保存起来,然后通过比较确定。链表、树、散列表(又叫哈希表,Hash table)等等数据结构都是这种思路。但是随着集合中元素的增加,我们需要的存储空间越来越大。同时检索速度也越来越慢,上述三种结构的检索时间复杂度分别为O(n),O(log n),O(1)。

布隆过滤器的原理是,当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。这就是布隆过滤器的基本思想。 –引自《维基百科,自由的百科全书》

本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure)高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”。相比于传统的 List、Set、Map 等数据结构,它更高效、占用空间更少,但是缺点是其返回的结果是概率性的,而不是确切的。

当你往简单数组或列表中插入新数据时,将不会根据插入项的值来确定该插入项的索引值。这意味着新插入项的索引值与数据值之间没有直接关系。这样的话,当你需要在数组或列表中搜索相应值的时候,你必须遍历已有的集合。若集合中存在大量的数据,就会影响数据查找的效率。

针对这个问题,你可以考虑使用哈希表。利用哈希表你可以通过对 “值” 进行哈希处理来获得该值对应的键或索引值,然后把该值存放到列表中对应的索引位置。这意味着索引值是由插入项的值所确定的,当你需要判断列表中是否存在该值时,只需要对值进行哈希处理并在相应的索引位置进行搜索即可,这时的搜索速度是非常快的。

二、布隆过滤器的结构

图片

根据定义,布隆过滤器可以检查值是 “可能在集合中” 还是 “绝对不在集合中”。“可能” 表示有一定的概率,也就是说可能存在一定为误判率。那为什么会存在误判呢?下面我们来分析一下具体的原因。
布隆过滤器(Bloom Filter)本质上是由长度为 m 的位向量或位列表(仅包含 0 或 1 位值的列表)组成,最初所有的值均设置为 0,如下图所示。

图片

为了将数据项添加到布隆过滤器中,我们会提供 K 个不同的哈希函数,并将结果位置上对应位的值置为 “1”。在前面所提到的哈希表中,我们使用的是单个哈希函数,因此只能输出单个索引值。而对于布隆过滤器来说,我们将使用多个哈希函数,这将会产生多个索引值。

图片

如上图所示,当输入 “semlinker” 时,预设的 3 个哈希函数将输出 2、4、6,我们把相应位置 1。假设另一个输入 ”kakuqo“,哈希函数输出 3、4 和 7。你可能已经注意到,索引位 4 已经被先前的 “semlinker” 标记了。此时,我们已经使用 “semlinker” 和 ”kakuqo“ 两个输入值,填充了位向量。当前位向量的标记状态为:

图片

当对值进行搜索时,与哈希表类似,我们将使用 3 个哈希函数对 ”搜索的值“ 进行哈希运算,并查看其生成的索引值。假设,当我们搜索 ”fullstack“ 时,3 个哈希函数输出的 3 个索引值分别是 2、3 和 7:

图片

从上图可以看出,相应的索引位都被置为 1,这意味着我们可以说 ”fullstack“ 可能已经插入到集合中。事实上这是误报的情形,产生的原因是由于哈希碰撞导致的巧合而将不同的元素存储在相同的比特位上。

那么我们如何选择哈希函数个数和布隆过滤器长度
很显然,过小的布隆过滤器很快所有的bit位均为1,那么查询任何值都会返回“可能存在”,起不到过滤的目的了。布隆过滤器的长度会直接影响误报率,布隆过滤器越长其误报率越小。

另外,哈希函数的个数也需要权衡,个数越多则布隆过滤器 bit 位置位 1 的速度越快,且布隆过滤器的效率越低;但是如果太少的话,那我们的误报率会变高。

图片

如何选择适合业务的 k 和 m 值呢,幸运的是,布隆过滤器有一个可预测的误判率(FPP):

图片

n 是已经添加元素的数量;
k 哈希的次数;
m 布隆过滤器的长度(如比特数组的大小);

极端情况下,当布隆过滤器没有空闲空间时(满),每一次查询都会返回 true 。这也就意味着 m 的选择取决于期望预计添加元素的数量 n ,并且 m 需要远远大于 n 。
实际情况中,布隆过滤器的长度 m 可以根据给定的误判率(FFP)的和期望添加的元素个数 n 的通过如下公式计算:

图片

了解完上述的内容之后,我们可以得出一个结论:当我们搜索一个值的时候,若该值经过 K 个哈希函数运算后的任何一个索引位为 ”0“,那么该值肯定不在集合中。但如果所有哈希索引值均为 ”1“,则只能说该搜索的值可能存在集合中。

三、布隆过滤器应用

在实际工作中,布隆过滤器常见的应用场景如下:

  • 网页爬虫对 URL 去重,避免爬取相同的 URL 地址;
  • 反垃圾邮件,从数十亿个垃圾邮件列表中判断某邮箱是否垃圾邮箱;
  • Google Chrome 使用布隆过滤器识别恶意 URL;
  • Medium 使用布隆过滤器避免推荐给用户已经读过的文章;
  • Google BigTable,Apache HBbase 和 Apache Cassandra 使用布隆过滤器减少对不存在的行和列的查找。

除了上述的应用场景之外,布隆过滤器还有一个应用场景就是解决缓存穿透的问题。所谓的缓存穿透就是服务调用方每次都是查询不在缓存中的数据,这样每次服务调用都会到数据库中进行查询,如果这类请求比较多的话,就会导致数据库压力增大,这样缓存就失去了意义。

利用布隆过滤器我们可以预先把数据查询的主键,比如用户 ID 或文章 ID 缓存到过滤器中。当根据 ID 进行数据查询的时候,我们先判断该 ID 是否存在,若存在的话,则进行下一步处理。若不存在的话,直接返回,这样就不会触发后续的数据库查询。需要注意的是缓存穿透不能完全解决,我们只能将其控制在一个可以容忍的范围内。

四、布隆过滤器的优缺点

优点
相比于其它的数据结构,布隆过滤器在空间和时间方面都有巨大的优势。布隆过滤器存储空间和插入/查询时间都是常数(O(k))。另外,散列函数相互之间没有关系,方便由硬件并行实现。布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势。

布隆过滤器可以表示全集,其它任何数据结构都不能;

k和m相同,使用同一组散列函数的两个布隆过滤器的交并运算可以使用位操作进行。

缺点
但是布隆过滤器的缺点和优点一样明显。误算率是其中之一。随着存入的元素数量增加,误算率随之增加。但是如果元素数量太少,则使用散列表足矣。

另外,一般情况下不能从布隆过滤器中删除元素。我们很容易想到把位数组变成整数数组,每插入一个元素相应的计数器加1, 这样删除元素时将计数器减掉就可以了。然而要保证安全地删除元素并非如此简单。首先我们必须保证删除的元素的确在布隆过滤器里面。这一点单凭这个过滤器是无法保证的。另外计数器回绕也会造成问题。

在降低误算率方面,有不少工作,使得出现了很多布隆过滤器的变种。

五、布隆过滤器实战

布隆过滤器有很多实现和优化,由 Google 开发著名的 Guava 库就提供了布隆过滤器(Bloom Filter)的实现。在基于 Maven 的 Java 项目中要使用 Guava 提供的布隆过滤器,只需要引入以下坐标:

<dependency>
   <groupId>com.google.guava</groupId>
   <artifactId>guava</artifactId>
   <version>28.0-jre</version>
</dependency>

复制代码在导入 Guava 库后,我们新建一个 BloomFilterDemo 类,在 main 方法中我们通过 BloomFilter.create 方法来创建一个布隆过滤器,接着我们初始化 1 百万条数据到过滤器中,然后在原有的基础上增加 10000 条数据并判断这些数据是否存在布隆过滤器中:

import com.google.common.base.Charsets;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;

public class BloomFilterDemo {
    public static void main(String[] args) {
        int total = 1000000; // 总数量
        BloomFilter<CharSequence> bf = 
          BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), total);
        // 初始化 1000000 条数据到过滤器中
        for (int i = 0; i < total; i++) {
            bf.put("" + i);
        }
        // 判断值是否存在过滤器中
        int count = 0;
        for (int i = 0; i < total + 10000; i++) {
            if (bf.mightContain("" + i)) {
                count++;
            }
        }
        System.out.println("已匹配数量 " + count);
    }
}

当以上代码运行后,控制台会输出以下结果:

已匹配数量 1000309

很明显以上的输出结果已经出现了误报,因为相比预期的结果多了 309 个元素,误判率为:

309/(1000000 + 10000) * 100 ≈ 0.030594059405940593

如果要提高匹配精度的话,我们可以在创建布隆过滤器的时候设置误判率 fpp:

BloomFilter<CharSequence> bf = BloomFilter.create(
  Funnels.stringFunnel(Charsets.UTF_8), total, 0.0002
);

在 BloomFilter 内部,误判率 fpp 的默认值是 0.03:

// com/google/common/hash/BloomFilter.class
public static <T> BloomFilter<T> create(Funnel<? super T> funnel, long expectedInsertions) {
  return create(funnel, expectedInsertions, 0.03D);
}

在重新设置误判率为 0.0002 之后,我们重新运行程序,这时控制台会输出以下结果:

已匹配数量 1000003

复制代码通过观察以上的结果,可知误判率 fpp 的值越小,匹配的精度越高。当减少误判率 fpp 的值,需要的存储空间也越大,所以在实际使用过程中需要在误判率和存储空间之间做个权衡。

六、总结

本文主要介绍的布隆过滤器的概念和常见的应用场合,在实战部分我们演示了 Google 著名的 Guava 库所提供布隆过滤器(Bloom Filter)的基本使用,同时我们也介绍了布隆过滤器出现误报的原因及如何提高判断准确性。最后为了便于大家理解布隆过滤器,我们介绍了一个简易版的布隆过滤器 SimpleBloomFilter。

在这里插入图片描述
JVM内存泄漏和内存溢出的原因
JVM常用监控工具解释以及使用
Redis 常见面试题(一)
ClickHouse之MaterializeMySQL引擎(十)
三种实现分布式锁的实现与区别
线程池的理解以及使用

号外!号外!

最近面试BAT,整理一份面试资料,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。想获取吗?如果你想提升自己,并且想和优秀的人一起进步,感兴趣的朋友,可以在扫码关注下方公众号。资料在公众号里静静的躺着呢。。。

点击下方微信公众号

  • 喜欢就收藏
  • 认同就点赞
  • 支持就关注
  • 疑问就评论

一键四连,你的offer也四连

————————————————

本文作者:Java技术债务
原文链接:https://www.cuizb.top/myblog/article/1644224367
版权声明: 本博客所有文章除特别声明外,均采用 CC BY 3.0 CN协议进行许可。转载请署名作者且注明文章出处。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么是布隆过滤器?如何使用? 的相关文章

  • 在java中将RFC3339 DateTime转换为Date [重复]

    这个问题在这里已经有答案了 如何转换RFC 3339 https www rfc editor org rfc rfc3339java 中的 com google api client util DateTime 到 DateTime 例如
  • 如何调试使用maven构建的android应用程序

    我目前正在尝试从 Eclipse 调试我的设备上的 Android 应用程序 设备已添加 我可以在控制台和 Eclipse 中看到它 控制台 Windows adb devices List of devices attached 0019
  • 为什么byteArray的长度是22而不是20?

    我们尝试从字符串转换为Byte 使用以下 Java 代码 String source 0123456789 byte byteArray source getBytes UTF 16 我们得到一个长度为 22 字节的字节数组 我们不确定这个
  • 使用Java获取CSS文件中图像的URL?

    我正在尝试使用 Java 获取远程 CSS 文件中图像 所有 MIME 类型 的 URL 我正在使用 jsoup 来获取 css 的 URL 经过无数个小时的观看CSS解析器 http cssparser sourceforge net 由
  • 使用 google-api-java-client 的 2 足 OAuth

    有谁知道如何将 2 legged OAuth 与 google api java client 一起使用 我正在尝试访问 Google Apps 配置 API 以获取特定域的用户列表 以下不起作用 HttpTransport transpo
  • 如何显示/隐藏jsf组件

    在我的一个 JSF 应用程序中 顶部的标题部分包含 selectOneMenu 底部的内容部分显示过滤器组件 默认情况下 应用程序首先在顶部显示 selectOneMenu 数据 在底部显示相应的 Filter 信息 如果用户选择不同的se
  • JFreeChart - 创建移动图表时出现问题

    我在我的 java 应用程序中使用 JFreeChart Problem 我想绘制一个XY面积图 whose 域轴 x 轴 当我们开始绘制数据时应该自动水平滚动 我在中看到了同样的事情时间序列图表但我不想要任何时间系列图表 我只想要滚动的
  • @Cachable 在没有输入参数的方法上?

    我有问题 org springframework cache annotation Cachable注解 Bean public ConcurrentMapCache cache return new ConcurrentMapCache
  • Tomcat - 多个 webapps 文件夹

    是否可以有多个文件夹来放置要部署的应用程序 这些是如何定义的 是否可以将一个文件夹限制为仅是 domain com 的应用程序 而不是其他域 Thanks 看一眼conf server xml
  • 维护插入顺序的并发集合[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个可以维护插入顺序的并发列表 有人有什么好的推荐吗 我看一些番石榴 例如SetFromMa
  • 在 JavaFX 中更改 ListView 字体大小

    我想知道如何更改 JavaFx 中的列表视图项目文本字体大小 每行文本的大小会有所不同 我尝试使用细胞因子属性 但我不知道如何使用它 有人可以帮我吗 类似的问题在这里 如何更改JavaFX中ListView的字体大小 https stack
  • iText7 将 SVG 添加到 PdfDocument 中以及可能出现的问题

    关于问题的答案 如何使用 iText7 将 SVG 添加到 PDF 这是一个链接点击这里 https stackoverflow com questions 50059456 how to add an svg to a pdf using
  • 如何在不同的班级中启动和停止计时器?

    我想测量从传入 HTTP 请求开始到应用程序到达某个点的时间 这两个时间点都位于不同的类中 我将如何启动和停止这些不同类别的计时器 我没有看到使用 MeterRegistry 中的 命名 计时器的方法 我该怎么办呢 您可以使用 AOP 如下
  • Wildfly 10.1 消耗所有核心

    我们最近将银行应用程序从 java 1 6 升级到 1 8 将 jboss 4 x 升级到 wildfly 10 1 我们观察到 java 消耗了机器上可用的所有核心 10 有人可以告诉是什么原因吗 通常情况下 jboss 4 x 的最大
  • 使用 InputStream 通过 TCP 套接字接收多个图像

    每次我从相机捕获图像时 我试图将多个图像自动从我的 Android 手机一张一张地发送到服务器 PC 问题是read 函数仅在第一次时阻塞 因此 从技术上讲 只有一张图像被接收并完美显示 但在那之后当is read 回报 1 该功能不阻塞
  • 如何从Java中的连接获取查询字符串?

    我正在编写一个方法 尝试记录数据库调用 形成连接到它的连接 在查询之后 有很多地方调用方法 connect 来启动并调用 cleanUp 方法来结束 我不能并且不想修改每个地方 所以顺序是这样的 Connection con connect
  • 文档过滤器在 Java 中不起作用?

    在超过 10 个字符的文本字段中 它必须显示错误 为此 我使用了文档过滤器 JTextField field JTextField txtFld AbstractDocument document AbstractDocument fiel
  • Java 中 .NET 的 Lambda 表达式

    我最近 再次 从 C 迁移到 Java 但我非常怀念 lambda 表达式和 C 的 IEnumerable Foreach 之类的东西 所以我正在寻找Java中的lambda表达式库 有比这更好的图书馆吗LambdaJ http code
  • Jackson 的 ObjectMapper 和 SQL 中的 RowMapper

    我们正在使用对象映射器 当将 ObjectMapper 与 RowMapper 一起使用时 是否应该在每个 mapRow 内部 如下所示 声明它 还是在 mapRow 外部声明为类公共成员 我认为根据本文 它应该作为公共类成员在外部 我应该
  • 在没有 ODBC 的情况下从 Java 操作 Access 数据库

    我想从我的 Java 项目操作 Microsoft Access 数据库 accdb 或 mdb 文件 我不想使用 Microsoft 的 JDBC ODBC Bridge 和 Access ODBC 驱动程序 因为 JDBC ODBC 桥

随机推荐

  • OpenCV图像处理实际案例(一)---图像倾斜矫正(仿射变换)和去边(轮廓查找+ROI提取)

    本博客算法及代码参考自贾志刚老师的 OpenCV图像处理 小案例实战 若涉及侵权问题 望通知 会第一时间删除 算法功能 1 图像角度倾斜矫正 基于仿射变换 2 去掉多余的边 轮廓查找 ROI提取 原始图像如下 算法思路 一 进行图像角度纠正
  • git 错误:GnuTLS recv error (-54): Error in the pull function

    最近在使用git时经常出现这个问题 google后说问题出现在一般libssh上 记录一下 我是直接使用这个命令就解决了这个问题 sudo apt get y install build essential nghttp2 libnghtt
  • Java中的集合

    目录 一 集合的概念 1 1什么是集合 1 2集合中具体有啥 二 集合中的Collection单列集合 2 1list集合 可存储重复元素 2 1 1Arraylist集合 2 1 2LinkedList集合 2 1 3Vector集合 2
  • 拥抱国产化,推动产业互联网,拍乐云做了什么?

    新一轮科学技术进步法的修订中提出要健全科技创新保障措施 完善创新体系 为促进实现高水平科技自立自强提供法治保障 随着国家对信息安全 科学自主的要求越来越高 音视频技术作为视频会议 应急指挥 办公协同 远程银行等行业场景的基础技术支撑 其独立
  • 【机器学习】欠拟合与过拟合总结

    目录 欠拟合与过拟合总结 一 欠拟合与过拟合的概念 二 欠拟合产生的原因与解决方法 三 过拟合产生的原因与解决方法 过拟合与欠拟合的区别在于 欠拟合在训练集和测试集上的性能都较差 而过拟合往往能较好地学习训练集数据的性质 而在测试集上的性能
  • 解决 Cannot find the specified class com.ibm.websphere.ssl.protocol.SSLSocketFactory报错问题

    背景说明 最近做接口开发时 需要调用调用第三方系统的接口 一开始用的是http的接口后来改为用https的协议 发现接口调用时会报错 java lang Exception 调用OA接口服务发生异常 java net SocketExcep
  • crmeb 标准版客服配置

    说明 此教程用于4 3 1 版本配置客服系统 1 首先放行服务器端口 info 提示 客服端口可自定义 目前系统默认使用 20002 20003 20012 端口 v4 3 0之后版本忽略本步骤 这里以阿里云服务器为参考 进入服务器安全组端
  • volume的含义_volume是什么意思

    你知道volume是什么意思吗X 在我们的日常生活中或在网络上 有时会听到或看到这样的词 下面我们一起来看看volume是什么意思吧 volume是什么意思 volume在计算机领域有 卷标 音量 之意 在股票用语上表示 成交量 成交金额及
  • leetcode----JavaScript 详情题解(3)

    目录 2667 创建 Hello World 函数 2677 分块数组 2693 使用自定义上下文调用函数 2695 包装数组 2703 返回传递的参数的长度 2704 相等还是不相等 2705 精简对象 2715 执行可取消的延迟函数 2
  • 北京时间--UNIX时间戳 相互转换

    UNIX时间戳 13位 10位 毫秒 秒 北京时间转换为13位时间戳 UTC 8 gt UTC gt 时间戳 e g DECLARE DATE DATETIME SET DATE DATEADD HOUR 8 2018 12 07 14 3
  • 华为od机试 Java 【单词前缀】

    题目 描述 给定一个单词前缀和一个字典 你的任务是从字典中找出所有以该前缀开头的单词 输入 输入的第一个单词是你要查找的前缀 接下来的数字表示字典中的单词数量 紧随其后的是字典中的单词 单词之间由空格分隔 输出 如果存在以给定前缀开头的单词
  • 【计算机网络】传输层协议-------TCP详解

    文章目录 1 TCP 协议概述 2 TCP原理 2 1 保持可靠性的机制 2 1 1 确认应答 2 1 2 超时重传 2 1 3 连接管理机制 安全机制 2 1 3 1 三次握手 2 1 3 2 四次挥手 2 1 4 滑动窗口 2 1 5
  • 在pycharm用python画图:matplotlib

    安装matplotlib 先找到自己的python位置 再进入Scripts文件夹 我的是C Users mi AppData Local Programs Python Python39 Scripts 一定要找对 否则下面的命令没有任何
  • Flex (SDK 4.5) 中直接使用 H.264 编码视频

    最近用到 Flex FMS 实现一个视频通信 而且需要用 H 264 编码 但 Flash 本身只能采用 VP6 H 263 编码 要想编码为 H 264 必须要利用第三方工具 Flash Media Live Encoder 这也是我不愿
  • 计算智能——感知器模型

    主要内容 1 感知器总述 2 感知器模型 3 感知器策略 建立损失函数 4 感知器算法 梯度下降和随机梯度下降 4 1梯度下降 4 2随机梯度下降 5 感知器MATLAB简单实现 5 1newp函数 5 2sim函数 5 3init函数 5
  • mysql提示表不存在的解决方法error: 1146: Table doesn't exist

    如果表真的不存在就新建对应表 如果存在 则 1 这种情况一般只要重启下数据库就能解决 2 或者把原来mysql安装目录data里的 ibdata1 文件也拷贝过去 不确定是否会影响MySQL里的原有数据库 请先备份ibdata1文件
  • HTML5是什么与什么合作推出的语言,H5和Html5是一回事吗?-- -H5和Html5问答

    经常有人问何为H5 或发个网页问是不是H5 真让回答 一两句也讲不清楚 所以先聊聊我理解的H5广告究竟如何定义 H5广告是什么 广告在生活中可是不新鲜了 不管你乐不乐意 带这个符号的传播物每天都在消耗着你的时间 你的精力 甚至还有你的情感
  • 内存数据库解析与主流产品对比(三)

    作者 实验室小陈 大数据开放实验室 在上一篇文章 内存数据库解析与主流产品对比 二 中 我们从数据组织和索引的角度介绍了内存数据库的特点和几款产品的技术实现 本文将继续解析内存数据库 从并发控制 持久化和查询处理的角度介绍几款技术 带来更多
  • Unity提高工作效率的终极指南

    本套课程指南通过关于如何更快 更智能地工作的最新技术 帮助Unity创作者节省时间并提高工作效率 你会学到 Unity的创建者节省了时间 提高了生产力 关于如何更快地使用程序员和艺术家工具集的技巧 无论是个人还是团队 Unity应该是一种快
  • 什么是布隆过滤器?如何使用?

    欢迎搜索 文章目录 一 布隆过滤器简介 二 布隆过滤器的结构 三 布隆过滤器应用 四 布隆过滤器的优缺点 五 布隆过滤器实战 六 总结 Redis缓存穿透可以通过布隆过滤器进行解决 那么什么是布隆过滤器呢 请往下看 通常你判断某个元素是否存