散列表、位图、布隆过滤器

三个方案整体上都可以很好的解决数据查找问题,细节上又有些区别。

【散列表、位图、布隆过滤器】散列表:散列表着眼于精确查询,这意味着散列表需要存储所有数据,通过高效的hash函数精确快速定位数据。这同时也带来了一个问题就是内存空间消耗,当面临大量数据时会面临硬件内存不支持的问题,关于这点我不确定它是否是一个悖论,比如我们是否真的有那么多的数据,这些数据是否真的有必要入缓存,这些数据是否存入的数据都是有效的。是的在系统设计时,我们存在热点数据一说,如果单纯的要求把所有数据存入缓存其实非常不合理。

位图:位图也是一个数据状态管理方案,位图通过一个一维数组存储数据状态,实际数据需要被转化为整数形式。这个很好的节约了存储空间,但是同时也失去了value的存储功能。空间的大小和数据的最大值有关。下面推荐一个算法:

5TB的硬盘上放满了数据,请写一个算法将这些数据进行排重。如果这些数据是一些32bit大小的数据该如何解决?如果是64bit的呢?
public static final int _1MB = 1024 * 1024; public static byte[] flags = new byte[ 512 * _1MB ]; public static void main(String[] args) { int[] array = {255, 1024, 0, 65536} int index = 0; for(int num : array) { if(!getFlags(num)) { //未出现的元素 array[index] = num; index = index + 1; //设置标志位 setFlags(num); } } } public static void setFlags(int num) { flags[num >> 3] |= 0x01 << (num & (0x07)); } public static boolean getFlags(int num) { return flags[num >> 3] >> (num & (0x07)) & 0x01; }



布隆过滤器:布隆过滤器是一种概率的状态管理方案,相对位图而言它通过牺牲准确性为代价,进一步节约了内存空间。布隆过滤器通过多重hash算法对一个值进行多点定位,但是不排除多个值映射到同一组定位点的问题。在不要求高精确度的前提下,是应对大数据的一种很好的解决方案。布隆过滤器错误率大家可以参考一下布隆过滤器的论文,在实践中google常用的设置比容量是数据的16倍,hash函数为8组的时候错误率在万分之一左右。
总结:隆过滤器可以说优化了位图算法,需要注意的一点是布隆过滤器更关注于数据的数量,位图更关注数据的最大值,但是以目前的计算机硬件水平来说他们最多也就是处理GB级别的数据量(条数或者最大值,而不是数据实际占用空间的大小,数据实际占用空间的大小往往比这个数量级更大)。然后在面临超大型数据比如PB级别,EB级别的时候,还是要用到数据持久化策略。

    推荐阅读