手摸手教你如何去重

文摘   职场   2022-03-31 16:40  

良好的业务带来的直接影响就是请求量增大,但对于程序猿来说,去重绝对是成长路上必踩的垫脚石;这些数据在转变为有效的业务数据前,往往需要进行清写(去重)处理……


  1. 客观情况

    1. 在数据量不太大的时候,通常采用一些内置的工具即可达到效果;反之,当数据量在百万级以后,要对2个数据集进去去重就要考虑数据能不能快速拿到占多少空间大概多久可以完成

  2. 布隆过滤器

    1. 原理

    2. 当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在

    3. 优缺点

  • 空间效率和查询效率高

  • 不会漏判,但是有一定的误判率(哈希表是精确匹配)

  • 删除困难。一个放入容器的元素映射到bit数组的k个位置上是1,删除的时候不能简单的直接置为0,可能会影响其他元素的判断




  • No can no bb


    /** * @Title: * @Package * @Description: 布隆过滤器 * @author: siri * @date: * @version: V1.0 */public class BloomFilterUtil { //定义一个质数数组作为hash的混淆值 private static final int[] PRIMES = new int[]{3 ,5,7,11,13,17,19,31}; //构建对应个数的 hash 算法,使值落在不同的标识位上 置为1 public static Hash[] ALGORITHM = new Hash[PRIMES.length]; //创建一个长度为千万级比特位 代表当前千万级数据 1^8 << 1^4 private static BitSet BITS = new BitSet(1<<8<<16);
    public BloomFilterUtil(){ for (int i = 0; i < PRIMES.length; i++) { ALGORITHM[i] = new Hash(PRIMES[i]); } }
    /** * 算出信息指纹 放置到对应的比特位上 * @param value */ public void add(String value){ for (Hash hash : ALGORITHM) { BITS.set(hash.hash(value),Boolean.TRUE); } }
    /** * 根据比特位上的值 检测是否包含当前 传入的value 存储误判 * @param value * @return */ public boolean contains(String value){ if(null == value){ return Boolean.FALSE; } boolean ret = Boolean.TRUE; for (Hash hash : ALGORITHM) { ret = ret && BITS.get(hash.hash(value)); } return ret; } /** * 自定义hash算法 */ private static class Hash { private int prime; Hash(int prime) { this.prime = prime; }
    int hash(String key){ int hash,i; for (hash = key.length(),i=0;i<key.length();i++){ hash+=key.charAt(i); } return hash % prime; } }}
  • Test

  • 哪些场景可用

    1. 网络爬虫过程中判断一个网址是否被访问过

    2. 英语单词拼写是否正确校验

    3. 垃圾邮箱过滤功能

    4. 大数据取名,某个名字是否已被占用

      每天进步一点点,有Bug就多一点 :)

    晚霞程序员
    一位需要不断学习的30+程序员……