zoukankan      html  css  js  c++  java
  • 如何快速判断一个key是否存在在亿级数据中(bloomFilters)

    面试题

    现在有一个非常庞大的数据(亿级),假设全是 int 类型。现在我给你一个数,你需要告诉我它是否存在其中(尽量高效)

    分析

    采用bloomFilters进行实现(时间&空间尽可能的有效),bloomFilters也常常用在防止缓存穿透,即服务请求在发送到缓存之前,先查找下bloomFilters,检查对应的key是否存在,不存在直接返回;存在再进入到缓存进行查询->DB查询

    实现思路:

    实际实现采用多次HASH,查看对应数组内存储的值是否为1,多次hash结果均为1,则认为是存在;存在一定的误判率;hash算法尽可能采用一致性hash方式,确保数据分布较为均匀

      1 package com.hero.cases;
      2 
      3 import com.beust.jcommander.internal.Lists;
      4 import org.junit.Assert;
      5 import org.junit.Test;
      6 
      7 import java.util.List;
      8 
      9 /**
     10  * @Des:判断亿级元素是否存在
     11  * @Auther: 飞狐
     12  * @Date: 2019/3/29
     13  */
     14 public class BloomFilters {
     15 
     16     /**
     17      * 数组长度
     18      */
     19     private int arraySize;
     20 
     21     private int[] array;
     22 
     23     public BloomFilters(int arraySize){
     24         this.arraySize = arraySize;
     25         array = new int[arraySize];
     26     }
     27 
     28     /**
     29      * 写入数据(经过3次Hash,把数组对应的位置标识为1)
     30      * @param key
     31      */
     32     public void add(String key){
     33         int first = hashcode_1(key);
     34         int second = hashcode_2(key);
     35         int third = hashcode_3(key);
     36 
     37         array[first % arraySize] = 1;
     38         array[second % arraySize] = 1;
     39         array[third % arraySize] = 1;
     40     }
     41 
     42 
     43     public int hashcode_1(String key){
     44         int hash = 0;
     45         int i ;
     46         for(i = 0; i < key.length(); i++){
     47             hash = 33 * hash + key.charAt(i);
     48         }
     49         return Math.abs(hash);
     50     }
     51 
     52 
     53     /**
     54      * FNV1_32_HASH算法
     55      * @param data
     56      * @return
     57      */
     58     private int hashcode_2(String data){
     59         final int p = 16777619;
     60         int hash = (int) 2166136261L;
     61         for(int i = 0; i < data.length(); i++){
     62             hash = (hash ^ data.charAt(i)) * p;
     63         }
     64         hash += hash << 13;
     65         hash ^= hash >> 7;
     66         hash += hash << 3;
     67         hash ^= hash >> 17;
     68         hash += hash << 5;
     69         
     70         return Math.abs(hash);
     71     }
     72 
     73     private int hashcode_3(String key){
     74         int hash,i;
     75         for(hash = 0, i= 0; i < key.length();++i){
     76             hash += key.charAt(i);
     77             hash += (hash << 10);
     78             hash ^= hash >> 6;
     79         }
     80         hash += hash << 3;
     81         hash ^= hash >> 11;
     82         hash += hash << 15;
     83         return Math.abs(hash);
     84     }
     85 
     86     /**
     87      * 判断元素是否存在
     88      * @param key
     89      * @return
     90      */
     91     public boolean check(String key){
     92         int first = hashcode_1(key);
     93         int second = hashcode_2(key);
     94         int third = hashcode_3(key);
     95 
     96         if(array[first % arraySize] == 0){
     97             return false;
     98         }
     99 
    100         if(array[second % arraySize] == 0){
    101             return false;
    102         }
    103 
    104         if(array[third % arraySize] == 0){
    105             return false;
    106         }
    107         return true;
    108     }
    109 
    110 }

    运行结果:

    检查1: true
    检查2: true
    检查3: true
    检查999999: true
    检查400230340: false
    执行时间:2261
    

      

  • 相关阅读:
    linux基础
    1-1python自动化测试环境搭建及开发工具安装
    Linux常用命令
    049.NET5_中间件
    045.NET5_基本鉴权授权
    044.NET5_基于Session_Cookies认证
    042-043.NET5_ResultFilter以及双语言应用
    041.NET5_ExceptionFilter
    040.NET5_ExceptionFilter
    039.NET5_自定义Filter匿名
  • 原文地址:https://www.cnblogs.com/feihufeihu/p/10641270.html
Copyright © 2011-2022 走看看