面试题

现在有一个非常庞大的数据(亿级),假设全是 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