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