精华内容
下载资源
问答
  • 布隆过滤器是可以用于判断一个元素是不是在一个集合里,并且相比于其它的数据结构,布隆过滤器在空间和时间方面都有巨大的优势。下面这篇文章主要给大家介绍了关于Java实现布隆过滤器的相关资料,需要的朋友可以参考下
  • 一耳光消息过滤器实现 的功能代码,效果不错
  • 使用java实现的布隆过滤器算法,jdk-1.7,使用java实现的布隆过滤器算法,jdk-1.7,使用java实现的布隆过滤器算法,jdk-1.7,
  • 下面小编就为大家带来一篇布隆过滤器(Bloom Filter)的Java实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 下面小编就为大家分享一篇Java实现简单文件过滤器功能,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • Java 实现的高性能布隆过滤器!.zip,Advanced Bloom Filter Based Algorithms for Efficient Approximate Data De-Duplication in Streams
  • java实现一个过滤器

    千次阅读 2016-03-06 21:48:07
     2、实现一个过滤器  一个过滤器实现主要是分以下4步去完成  ①写一个java类,实现Filter接口。  ②在doFilter方法里面实现拦截处理逻辑。  ③配置过滤器(web.xml)  ④把过滤器和web项目一起打包部署 3、...
    1、过滤器
        servlet规范当中定义的一种特殊的组件,用来拦截容器的调用过程。
     2、实现一个过滤器
        一个过滤器的实现主要是分以下4步去完成
        ①写一个java类,实现Filter接口。
        ②在doFilter方法里面实现拦截处理逻辑。
        ③配置过滤器(web.xml)
        ④把过滤器和web项目一起打包部署
    3、用过滤器实现屏蔽敏感词汇
        ①写一个java类,实现Filter接口。
              public class MyFilter implements Filter
         ②在doFilter方法里面实现拦截处理逻辑。
     package test1;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    
    
    public class MyFilter implements Filter{
        private FilterConfig config; //获得config对象,用于读取配置文件中的内容
        public void destroy() {
            // TODO Auto-generated method stub
    
        }
        /**
         * 容器会调用doFilter方法来处理请求.
         * 容器会将request和respnse做为参数来调用该方法.
         * FilterChain(过滤器链),如果调用了该对象的doFilter方法,容器会继续向后调用。
         */
        public void doFilter(ServletRequest arg0, ServletResponse arg1,
                FilterChain arg2) throws IOException, ServletException {
            // TODO Auto-generated method stub
            //将ServletResponse和ServletRequest向下造型为HtppServletResponse和HttpServletRequest
            HttpServletRequest request = (HttpServletRequest)arg0;
            HttpServletResponse response = (HttpServletResponse)arg1;
            //设置编码
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
            //获得输入的内容
            String content = request.getParameter("content");
            PrintWriter out = response.getWriter();
            //从配置文件中读取初始化参数
            String illegalStr = config.getInitParameter("illegalStr");
            if(content.indexOf(illegalStr)!=-1){
                out.println("你输入的内容非法");
            }else{
                //继续向后调用
                arg2.doFilter(arg0, arg1);
            }
    
        }
        /**
         * 实例化之后容器会调用init方法,该方法只会执行一次。
         * FilterConfig可以用来读取初始化参数
         */
        public void init(FilterConfig arg0) throws ServletException {
            // TODO Auto-generated method stub
            config = arg0;
        }
    
    }

    ③配置过滤器(web.xml) 这里只展示屏蔽了“操”这个敏感字
      <filter>
             <filter-name>filter</filter-name>
             <filter-class>web.MyFilter</filter-class>
             <init-param>
                 <param-name>illegalStr</param-name>
                 <param-value>操</param-value>
             </init-param>
         </filter>
         <filter-mapping>
             <filter-name>filter</filter-name>
             <url-pattern>/myfilter</url-pattern>
         </filter-mapping>
    注:
         当有多个过滤器都满足过滤的条件,则容器依据<filter-mapping>的先后顺序来调用各个过滤器。
    ④把过滤器和web项目一起打包部署
     package test1;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class process extends HttpServlet {
    
        public void service(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
    
            request.setCharacterEncoding("utf-8");
            response.setContentType("text/html;charset=utf-8");
            PrintWriter out = response.getWriter();
             String content = request.getParameter("content");
             out.println("你输入的内容是:"+content);
    
        }
    
    }
    

    测试:


    展开全文
  • 布隆过滤器 java实现代码

    热门讨论 2012-06-29 11:16:23
    布隆过滤器 源码 java版 /** * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software ...
  • 主要介绍了Java Web实现session过期后自动跳转到登陆页功能,涉及java过滤器针对session的判断与跳转相关操作技巧,需要的朋友可以参考下
  • Java实现布隆过滤器

    千次阅读 2020-05-11 15:47:03
    Java 实现布隆过滤器 1.什么是布隆过滤器? 布隆过滤器(Bloom Filter)是一个叫做 Bloom 的老哥于1970年提出的。 实际上可以把它看作由二进制向量(或者说位数组)和一系列随机映射函数(哈希函数)两部分组成的...

    1.什么是布隆过滤器?

    • 布隆过滤器(Bloom Filter)是一个叫做 Bloom 的老哥于1970年提出的。
    • 实际上可以把它看作由二进制向量(或者说位数组)和一系列随机映射函数(哈希函数)两部分组成的数据结构。
    • 它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。

    在这里插入图片描述

    2.布隆过滤器的原理介绍

    • 图解:

    在这里插入图片描述

    • 如图所示,布隆过滤器添加元素时,该元素首先由多个哈希函数生成不同的哈希值,然后在对应的位数组的下表的元素设置为 1(当位数组初始化时 ,所有位置均为0)。当第二次存储相同字符串时,因为先前的对应位置已设置为1,所以很容易知道此值已经存在。

    • 如果我们需要判断某个元素是否在布隆过滤器中时,只需要对给定字符串再次进行相同的哈希计算,得到值之后判断位数组中的每个元素是否都为 1,如果值都为 1,那么说明这个值在布隆过滤器中,如果存在一个值不为 1,说明该元素不在布隆过滤器中。

    • 不同的字符串可能哈希出来的位置相同,这种情况我们可以适当增加位数组大小或者调整我们的哈希函数。

    • 所以,布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。

    3.布隆过滤器使用场景

    1. 判断给定数据是否存在。
    2. 防止缓存穿透(判断请求的数据是否有效避免直接绕过缓存请求数据库)等等、邮箱的垃圾邮件过滤、黑名单功能等等。。

    4.用Java 实现布隆过滤器

    • 下面是我参考网上已有代码改的:
    /**
     * 布隆过滤器
     *
     * @author wangjie
     * @version V1.0
     * @date 2020/5/11
     */
    public class BloomFilterDemo {
        /**
         * 位数组的大小
         */
        private static  int SIZE;
        /**
         * 通过这个数组可以创建不同的哈希函数
         */
        private static  int[] SEEDS;
        /**
         * 位数组。数组中的元素只能是 0 或者 1
         */
        private BitSet bits;
    
        /**
         * 存放包含 hash 函数的类的数组
         */
        private SimpleHash[] func;
        /**
         * 误判率
         */
        private MisjudgmentRate rate;
        /**
         * 自动清空
         */
        private  Double autoClearRate;
        /**
         * 使用数量
         */
        private final AtomicInteger useCount = new AtomicInteger(0);
        /**
         * 静态内部类。hash 函数
         */
        public static class SimpleHash {
    
            private int cap;
            private int seed;
    
            public SimpleHash(int cap, int seed) {
                this.cap = cap;
                this.seed = seed;
            }
    
            /**
             * 计算 hash 值
             */
            public int hash(Object value) {
                int h;
                return (value == null) ? 0 : Math.abs(seed * (cap - 1) & ((h = value.hashCode()) ^ (h >>> 16)));
            }
    
        }
    
        /**
         * 误判率
         */
        public enum MisjudgmentRate {
            /**
             * 每个字符串分配4个位
             */
            VERY_SMALL(new int[] { 2, 3, 5, 7 }),
            /**
             * 每个字符串分配8个位
             */
            SMALL(new int[] { 2, 3, 5, 7, 11, 13, 17, 19 }),
            /**
             * 每个字符串分配16个位
             */
            MIDDLE(new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 }),
            /**
             * 每个字符串分配32个位
             */
            HIGH(new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
                    101, 103, 107, 109, 113, 127, 131 });
    
            private int[] seeds;
    
            private MisjudgmentRate(int[] seeds) {
                this.seeds = seeds;
            }
    
            public int[] getSeeds() {
                return seeds;
            }
    
            public void setSeeds(int[] seeds) {
                this.seeds = seeds;
            }
    
        }
    
        /**
         * 默认中等程序的误判率
         * @param dataCount 预期处理的数据规模,如预期用于处理1百万数据的查重,这里则填写1000000
         */
        public BloomFilterDemo(int dataCount){
            this(MisjudgmentRate.MIDDLE, dataCount, null);
        }
    
        /**
         *
         * @param rate 枚举类型的误判率
         * @param dataCount 预期处理的数据规模,如预期用于处理1百万数据的查重,这里则填写1000000
         * @param autoClearRate 自动清空过滤器内部信息的使用比率
         */
        public BloomFilterDemo(MisjudgmentRate rate, int dataCount, Double autoClearRate){
            long bitSize = rate.seeds.length * dataCount;
            if (bitSize < 0 || bitSize > Integer.MAX_VALUE) {
                throw new RuntimeException("位数太大溢出了,请降低误判率或者降低数据大小");
            }
            this.rate = rate;
            SEEDS = rate.seeds;
            SIZE = (int) bitSize;
            func = new SimpleHash[SEEDS.length];
            for (int i = 0; i < SEEDS.length; i++) {
                func[i] = new SimpleHash(SIZE, SEEDS[i]);
            }
            bits = new BitSet(SIZE);
            this.autoClearRate = autoClearRate;
        }
    
        /**
         * 添加元素到位数组
         */
        public void add(Object value) {
    
            checkNeedClear();
    
            if(!contains(value)){
    	       for (SimpleHash f : func) {
    	           bits.set(f.hash(value), true);
    	       }
    	       useCount.getAndIncrement();
            }
            
        }
    
        /**
         * 判断指定元素是否存在于位数组
         */
        public boolean contains(Object value) {
            boolean ret = true;
            for (SimpleHash f : func) {
                ret = ret && bits.get(f.hash(value));
            }
            return ret;
        }
    
        /**
         * 检查是否需要清空
         */
        private void checkNeedClear() {
            if (autoClearRate != null) {
                if (getUseRate() >= autoClearRate) {
                    synchronized (this) {
                        if (getUseRate() >= autoClearRate) {
                            bits.clear();
                            useCount.set(0);
                        }
                    }
                }
            }
        }
        public double getUseRate() {
            return (double) useCount.intValue() / (double) SIZE;
        }
    
        public static void main(String[] args) {
            String value1 = "fffdfg";
            String value2 = "ddbgbfgbfbbgfb";
            BloomFilterDemo filter = new BloomFilterDemo(2<<24);
            System.out.println(filter.contains(value1));
            System.out.println(filter.contains(value2));
            filter.add(value1);
            filter.add(value2);
            System.out.println(filter.contains(value1));
            System.out.println(filter.contains(value2));
            Integer value11 = 13423;
            Integer value21 = 22131;
            System.out.println(filter.contains(value11));
            System.out.println(filter.contains(value21));
            filter.add(value11);
            filter.add(value21);
            System.out.println(filter.contains(value11));
            System.out.println(filter.contains(value21));
        }
    
    }
    
    • 运行结果:
    false
    false
    true
    true
    false
    false
    true
    true
    
    展开全文
  • JAVA字符集过滤器函数代码
  • 下面小编就为大家带来一篇java 过滤器filter防sql注入的实现代码。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 敏感词、文字过滤是一个网站必不可少的功能,本篇文章主要介绍了Java实现敏感词过滤实例,具有一定的参考价值,有需要的可以了解一下。
  • JAVA过滤器及原理

    2018-11-25 19:42:00
    JAVA过滤器,原理介绍,基本Demo,里面有图文教程,有源码分析,有代码Demo,欢迎大家下载学习,讨论
  • Servlet过滤器简介 Servlet过滤器实际上就是一个标准的java类,这个类通过实现Filter接口获得过滤器的功能。它在jsp容器启动的时候通过web.xml配置文件被系统加载。Servlet过滤器在接收到用户请求的时候被调用,当...
  • 该压缩包实现了利用过滤器或者拦截器对登录信息进行验证跳转登陆页的功能,利用的是SpringBoot和thymeleaf,使用前请先看使用说明
  • Logstash过滤器Java 通过实现Java接口编写logstash过滤器
  • 主要介绍了JAVA正则表达式过滤文件的实现方法的相关资料,希望通过本文大家能够掌握理解这部分内容,需要的朋友可以参考下
  • 主要介绍了Java实现循环体的过滤器的方法,需要的朋友可以参考下
  • 主要为大家详细介绍了cookie、session和java过滤器结合实现登陆程序的具体代码,感兴趣的朋友可以参考一下
  • MsgProcessor是消息管理类,setMsg方法设置消息字符串。HTMLFilter的功能是将尖括号替换成中括号;SesitiveFilter的功能是将消息中的敏感词过滤掉;FaceFilter的功能是将笑脸替换成另一种表情符号。
  • 本文实例讲述了thinkPHP框架实现类似java过滤器的简单方法。分享给大家供大家参考,具体如下: 写java web代码的时候,可以定义过滤器,对控制器进行过滤,可以实现权限验证等等 在thinkphp中也可以通过继承父类的...
  • Filter也称之为过滤器,它是Servlet技术中最实用的技术,本文章WEB开发人员通过Filter技术,对web服务器管理的所有web资源进行拦截,从而实现一些特殊的功能,本文章将向大家介绍Java 中的 Filter 过滤器,需要的朋友...
  • 对项目中的所有参数去除前后空格...可以基于此过滤器实现过滤跨站脚本攻击,参数的增加,修改!敏感词汇过滤。实现原理为重写HttpServletRequestWrapper,获取参数的方法。include和 Forwarded 内部转发不在过滤之内。
  • 使用Java多线程实现管道过滤器,本文档写了六个线程,五个管道,内容很简单,如果想要复杂功能请手动添加。
  • 主要介绍了JAVA实现较完善的布隆过滤器的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • JAVA实现较完善的布隆过滤器

    万次阅读 多人点赞 2017-07-30 17:17:22
    布隆过滤器是可以用于判断一个元素是不是在一个集合里,并且相比于其它的数据结构,布隆过滤器...简单来说,布隆过滤器实现方法就是:利用内存中一个长度为M的位数组B并初始化里面的所有位都为0,如下面的表格所示:

    布隆过滤器是可以用于判断一个元素是不是在一个集合里,并且相比于其它的数据结构,布隆过滤器在空间和时间方面都有巨大的优势。布隆过滤器存储空间和插入/查询时间都是常数。但是它也是拥有一定的缺点:布隆过滤器是有一定的误识别率以及删除困难的。本文中给出的布隆过滤器的实现,基本满足了日常使用所需要的功能。


    先简单来说一下布隆过滤器。其实现方法就是:利用内存中一个长度为M的位数组B并初始化里面的所有位都为0,如下面的表格所示:

    0000000000

    然后我们根据H个不同的散列函数,对传进来的字符串进行散列,并且每次的散列结果都不能大于位数组的长度。布隆过滤器的误判率取决于你使用多少个不同的散列函数,下面给出的代码中,给出了一些参考的误判率(参考代码中的枚举类:MisjudgmentRate)。现在我们先假定有4个不同散列函数,传入一个字符串并进行一次插入操作,这时会进行4次散列,假设到了4个不同的下标,这个时候我们就会去数组中,将这些下标的位置置为1,数组变更为:

    0101100001

    如果接下来我们再传入同一个字符串时,因为4次的散列结果都是跟上一次一样的,所以会得出跟上面一样的结果,所有应该置1的位都已经置1了,这个时候我们就可以认为这个字符串是已经存在的了。因此不难发现,这是会存在一定的误判率的,具体由你采用的散列函数质量,以及散列函数的数量确定。

    代码如下:

    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    import java.util.BitSet;
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class BloomFileter implements Serializable {
    	private static final long serialVersionUID = -5221305273707291280L;
    	private final int[] seeds;
    	private final int size;
    	private final BitSet notebook;
    	private final MisjudgmentRate rate;
    	private final AtomicInteger useCount = new AtomicInteger(0);
    	private final Double autoClearRate;
    
    	/**
    	 * 默认中等程序的误判率:MisjudgmentRate.MIDDLE 以及不自动清空数据(性能会有少许提升)
    	 * 
    	 * @param dataCount
    	 *            预期处理的数据规模,如预期用于处理1百万数据的查重,这里则填写1000000
    	 */
    	public BloomFileter(int dataCount) {
    		this(MisjudgmentRate.MIDDLE, dataCount, null);
    	}
    
    	/**
    	 * 
    	 * @param rate
    	 *            一个枚举类型的误判率
    	 * @param dataCount
    	 *            预期处理的数据规模,如预期用于处理1百万数据的查重,这里则填写1000000
    	 * @param autoClearRate
    	 *            自动清空过滤器内部信息的使用比率,传null则表示不会自动清理,
    	 *            当过滤器使用率达到100%时,则无论传入什么数据,都会认为在数据已经存在了
    	 *            当希望过滤器使用率达到80%时自动清空重新使用,则传入0.8
    	 */
    	public BloomFileter(MisjudgmentRate rate, int dataCount, Double autoClearRate) {
    		long bitSize = rate.seeds.length * dataCount;
    		if (bitSize < 0 || bitSize > Integer.MAX_VALUE) {
    			throw new RuntimeException("位数太大溢出了,请降低误判率或者降低数据大小");
    		}
    		this.rate = rate;
    		seeds = rate.seeds;
    		size = (int) bitSize;
    		notebook = new BitSet(size);
    		this.autoClearRate = autoClearRate;
    	}
    
    	public void add(String data) {
    		checkNeedClear();
    
    		for (int i = 0; i < seeds.length; i++) {
    			int index = hash(data, seeds[i]);
    			setTrue(index);
    		}
    	}
    
    	public boolean check(String data) {
    		for (int i = 0; i < seeds.length; i++) {
    			int index = hash(data, seeds[i]);
    			if (!notebook.get(index)) {
    				return false;
    			}
    		}
    		return true;
    	}
    
    	/**
    	 * 如果不存在就进行记录并返回false,如果存在了就返回true
    	 * 
    	 * @param data
    	 * @return
    	 */
    	public boolean addIfNotExist(String data) {
    		checkNeedClear();
    
    		int[] indexs = new int[seeds.length];
    		// 先假定存在
    		boolean exist = true;
    		int index;
    
    		for (int i = 0; i < seeds.length; i++) {
    			indexs[i] = index = hash(data, seeds[i]);
    
    			if (exist) {
    				if (!notebook.get(index)) {
    					// 只要有一个不存在,就可以认为整个字符串都是第一次出现的
    					exist = false;
    					// 补充之前的信息
    					for (int j = 0; j <= i; j++) {
    						setTrue(indexs[j]);
    					}
    				}
    			} else {
    				setTrue(index);
    			}
    		}
    
    		return exist;
    
    	}
    
    	private void checkNeedClear() {
    		if (autoClearRate != null) {
    			if (getUseRate() >= autoClearRate) {
    				synchronized (this) {
    					if (getUseRate() >= autoClearRate) {
    						notebook.clear();
    						useCount.set(0);
    					}
    				}
    			}
    		}
    	}
    
    	public void setTrue(int index) {
    		useCount.incrementAndGet();
    		notebook.set(index, true);
    	}
    
    	private int hash(String data, int seeds) {
    		char[] value = data.toCharArray();
    		int hash = 0;
    		if (value.length > 0) {
    
    			for (int i = 0; i < value.length; i++) {
    				hash = i * hash + value[i];
    			}
    		}
    	
    		hash = hash * seeds % size;
    		// 防止溢出变成负数
    		return Math.abs(hash);
    	}
    
    	public double getUseRate() {
    		return (double) useCount.intValue() / (double) size;
    	}
    
    	public void saveFilterToFile(String path) {
    		try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path))) {
    			oos.writeObject(this);
    		} catch (Exception e) {
    			throw new RuntimeException(e);
    		}
    
    	}
    
    	public static BloomFileter readFilterFromFile(String path) {
    		try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path))) {
    			return (BloomFileter) ois.readObject();
    		} catch (Exception e) {
    			throw new RuntimeException(e);
    		}
    	}
    
    	/**
    	 * 清空过滤器中的记录信息
    	 */
    	public void clear() {
    		useCount.set(0);
    		notebook.clear();
    	}
    
    	public MisjudgmentRate getRate() {
    		return rate;
    	}
    
    	/**
    	 * 分配的位数越多,误判率越低但是越占内存
    	 * 
    	 * 4个位误判率大概是0.14689159766308
    	 * 
    	 * 8个位误判率大概是0.02157714146322
    	 * 
    	 * 16个位误判率大概是0.00046557303372
    	 * 
    	 * 32个位误判率大概是0.00000021167340
    	 * 
    	 * @author lianghaohui
    	 *
    	 */
    	public enum MisjudgmentRate {
    		// 这里要选取质数,能很好的降低错误率
    		/**
    		 * 每个字符串分配4个位
    		 */
    		VERY_SMALL(new int[] { 2, 3, 5, 7 }),
    		/**
    		 * 每个字符串分配8个位
    		 */
    		SMALL(new int[] { 2, 3, 5, 7, 11, 13, 17, 19 }), //
    		/**
    		 * 每个字符串分配16个位
    		 */
    		MIDDLE(new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 }), //
    		/**
    		 * 每个字符串分配32个位
    		 */
    		HIGH(new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
    				101, 103, 107, 109, 113, 127, 131 });
    
    		private int[] seeds;
    
    		private MisjudgmentRate(int[] seeds) {
    			this.seeds = seeds;
    		}
    
    		public int[] getSeeds() {
    			return seeds;
    		}
    
    		public void setSeeds(int[] seeds) {
    			this.seeds = seeds;
    		}
    
    	}
    
    	public static void main(String[] args) {
    		BloomFileter fileter = new BloomFileter(7);
    		System.out.println(fileter.addIfNotExist("1111111111111"));
    		System.out.println(fileter.addIfNotExist("2222222222222222"));
    		System.out.println(fileter.addIfNotExist("3333333333333333"));
    		System.out.println(fileter.addIfNotExist("444444444444444"));
    		System.out.println(fileter.addIfNotExist("5555555555555"));
    		System.out.println(fileter.addIfNotExist("6666666666666"));
    		System.out.println(fileter.addIfNotExist("1111111111111"));
    		fileter.saveFilterToFile("C:\\Users\\john\\Desktop\\1111\\11.obj");
    		fileter = readFilterFromFile("C:\\Users\\john\\Desktop\\111\\11.obj");
    		System.out.println(fileter.getUseRate());
    		System.out.println(fileter.addIfNotExist("1111111111111"));
    	}
    }
    



    展开全文
  • 主要介绍了Java web过滤器验证登录防止未登录进入界面,在一些系统中经常可以用到此功能,对java web 验证登录知识感兴趣的朋友一起看下吧
  • 布隆过滤器以及java实现

    万次阅读 2019-06-12 11:23:18
    Java实现简单的布隆过滤器 //https://blog.csdn.net/u014653197/article/details/76397037 public class BloomFilter implements Serializable{ private final int[] seeds; private final int size; ...

    bloom算法类似一个hash set,用来判断某个元素(key)是否在某个集合中。和一般的hash set不同的是,这个算法无需存储key的值,对于每个key,只需要k个比特位,每个存储一个标志,用来判断key是否在集合中。

    算法:
    1. 首先需要k个hash函数,每个函数可以把key散列成为1个整数
    2. 初始化时,需要一个长度为n比特的数组,每个比特位初始化为0
    3. 某个key加入集合时,用k个hash函数计算出k个散列值,并把数组中对应的比特位置为1
    4. 判断某个key是否在集合时,用k个hash函数计算出k个散列值,并查询数组中对应的比特位,如果所有的比特位都是1,认为在集合中。

    优点:不需要存储key,节省空间;缺点:1. 算法判断key在集合中时,有一定的概率key其实不在集合中 2. 无法删除。

    有一个长度为m的bit型数组,如我们所知,每个位置只占一个bit,每个位置只有0和1两种状态。假设一共有k个哈希函数相互独立,输入域都为s且都大于等于m,那么对同一个输入对象(可以想象为缓存中的一个key),经过k个哈希函数计算出来的结果也都是独立的。对算出来的每一个结果都对m取余,然后在bit数组上把相应的位置设置为1(描黑),如下图所示:

                               

    布隆过滤器的误判率

    假设 Hash 函数以等概率条件选择并设置 Bit Array 中的某一位,m 是该位数组的大小,k 是 Hash 函数的个数,那么位数组中某一特定的位在进行元素插入时的 Hash 操作中没有被置位的概率是:

    那么在所有 k 次 Hash 操作后该位都没有被置 "1" 的概率是:

    如果我们插入了 n 个元素,那么某一位仍然为 "0" 的概率是:

    因而该位为 "1"的概率是:

    现在检测某一元素是否在该集合中。标明某个元素是否在集合中所需的 k 个位置都按照如上的方法设置为 "1",但是该方法可能会使算法错误的认为某一原本不在集合中的元素却被检测为在该集合中(False Positives),该概率由以下公式确定:

    布隆过滤器的大小m公式:

                                                                                       

    哈希函数的个数k公式:

                                                                                  

    布隆过滤器真实失误率p公式:

                                                                                               

    假设缓存系统,key为userId,value为user。如果我们有10亿个用户,规定失误率不能超过0.01%,通过计算器计算可得m=19.17n,向上取整为20n,也就是需要200亿个bit,换算之后所需内存大小就是2.3G。通过第二个公式可计算出所需哈希函数k=14.因为在计算m的时候用了向上取整,所以真实的误判率绝对小于等于0.01%。

    布隆过滤器可以使用google已经实现的jar

    <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>25.1-jre</version>
    </dependency>

     

    Java实现简单的布隆过滤器

    //https://blog.csdn.net/u014653197/article/details/76397037
    public class BloomFilter implements Serializable{
    	
    	private final int[] seeds;
    	private final int size;
    	private final BitSet notebook;
    	private final MisjudgmentRate rate;
    	private final AtomicInteger useCount = new AtomicInteger();
    	private final Double autoClearRate;
    	
    	//dataCount逾预期处理的数据规模
    	public BloomFilter(int dataCount){
    		this(MisjudgmentRate.MIDDLE, dataCount, null);
    	}
    	
    	//自动清空过滤器内部信息的使用比率,传null则表示不会自动清理;
    	//当过滤器使用率达到100%时,则无论传入什么数据,都会认为在数据已经存在了;
    	//当希望过滤器使用率达到80%时自动清空重新使用,则传入0.8
    	public BloomFilter(MisjudgmentRate rate, int dataCount, Double autoClearRate){
    		//每个字符串需要的bit位数*总数据量
    		long bitSize = rate.seeds.length * dataCount;
    		if(bitSize<0 || bitSize>Integer.MAX_VALUE){
    			throw new RuntimeException("位数太大溢出了,请降低误判率或者降低数据大小");
    		}
    		this.rate = rate;
    		seeds = rate.seeds;
    		size = (int)bitSize;
    		//创建一个BitSet位集合
    		notebook = new BitSet(size);
    		this.autoClearRate = autoClearRate;
    	}
    	
    	//如果存在返回true,不存在返回false
    	public boolean addIfNotExist(String data){
    		//是否需要清理
    		checkNeedClear();
    		//seeds.length决定每一个string对应多少个bit位,每一位都有一个索引值
    		//给定data,求出data字符串的第一个索引值index,如果第一个index值对应的bit=false说明,该data值不存在,则直接将所有对应bit位置为true即可;
    		//如果第一个index值对应bit=true,则将index值保存,但此时并不能说明data已经存在,
    		//则继续求解第二个index值,若所有index值都不存在则说明该data值不存在,将之前保存的index数组对应的bit位置为true
    		int[] indexs = new int[seeds.length];
    		//假定data已经存在
    		boolean exist = true;
    		int index;
    		for(int i=0; i<seeds.length; i++){
    			//计算位hash值
    			indexs[i] = index = hash(data, seeds[i]);
    			if(exist){
    				//如果某一位bit不存在,则说明该data不存在
    				if(!notebook.get(index)){
    					exist = false;
    					//将之前的bit位置为true
    					for(int j=0; j<=i; j++){
    						setTrue(indexs[j]);
    					}
    				}
    			}else{
    				//如果不存在则直接置为true
    				setTrue(index);
    			}
    		}
    		
    		return exist;
    	}
    	
    	private int hash(String data, int seeds) {
    		char[] value = data.toCharArray();
    		int hash = 0;
    		if(value.length>0){
    			for(int i=0; i<value.length; i++){
    				hash = i * hash + value[i];
    			}
    		}
    		hash = hash * seeds % size;
    		return Math.abs(hash);
    	}
    
    	private void setTrue(int index) {
    		useCount.incrementAndGet();
    		notebook.set(index, true);
    	}
    
    	//如果BitSet使用比率超过阈值,则将BitSet清零
    	private void checkNeedClear() {
    		if(autoClearRate != null){
    			if(getUseRate() >= autoClearRate){
    				synchronized (this) {
    					if(getUseRate() >= autoClearRate){
    						notebook.clear();
    						useCount.set(0);
    					}
    				}
    			}
    		}
    	}
    
    	private Double getUseRate() {
    		return (double)useCount.intValue()/(double)size;
    	}
    	
    	public void saveFilterToFile(String path) {
    		try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path))) {
    			oos.writeObject(this);
    		} catch (Exception e) {
    			throw new RuntimeException(e);
    		}
     
    	}
     
    	public static BloomFilter readFilterFromFile(String path) {
    		try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path))) {
    			return (BloomFilter) ois.readObject();
    		} catch (Exception e) {
    			throw new RuntimeException(e);
    		}
    	}
     
    	/**
    	 * 清空过滤器中的记录信息
    	 */
    	public void clear() {
    		useCount.set(0);
    		notebook.clear();
    	}
     
    	public MisjudgmentRate getRate() {
    		return rate;
    	}
    	
    	/**
    	 * 分配的位数越多,误判率越低但是越占内存
    	 * 
    	 * 4个位误判率大概是0.14689159766308
    	 * 
    	 * 8个位误判率大概是0.02157714146322
    	 * 
    	 * 16个位误判率大概是0.00046557303372
    	 * 
    	 * 32个位误判率大概是0.00000021167340
    	 *
    	 */
    	public enum MisjudgmentRate {
    		// 这里要选取质数,能很好的降低错误率
    		/**
    		 * 每个字符串分配4个位
    		 */
    		VERY_SMALL(new int[] { 2, 3, 5, 7 }),
    		/**
    		 * 每个字符串分配8个位
    		 */
    		SMALL(new int[] { 2, 3, 5, 7, 11, 13, 17, 19 }), //
    		/**
    		 * 每个字符串分配16个位
    		 */
    		MIDDLE(new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 }), //
    		/**
    		 * 每个字符串分配32个位
    		 */
    		HIGH(new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
    				101, 103, 107, 109, 113, 127, 131 });
    		
    		private int[] seeds;
    		
    		//枚举类型MIDDLE构造函数将seeds数组初始化
    		private MisjudgmentRate(int[] seeds) {
    			this.seeds = seeds;
    		}
    		
    		public int[] getSeeds() {
    			return seeds;
    		}
    		
    		public void setSeeds(int[] seeds) {
    			this.seeds = seeds;
    		}
    	}
    	
    	public static void main(String[] args) {
    		BloomFilter fileter = new BloomFilter(7);
    		System.out.println(fileter.addIfNotExist("1111111111111"));
    		System.out.println(fileter.addIfNotExist("2222222222222222"));
    		System.out.println(fileter.addIfNotExist("3333333333333333"));
    		System.out.println(fileter.addIfNotExist("444444444444444"));
    		System.out.println(fileter.addIfNotExist("5555555555555"));
    		System.out.println(fileter.addIfNotExist("6666666666666"));
    		System.out.println(fileter.addIfNotExist("1111111111111"));
    		//fileter.saveFilterToFile("C:\\Users\\john\\Desktop\\1111\\11.obj");
    		//fileter = readFilterFromFile("C:\\Users\\john\\Desktop\\111\\11.obj");
    		System.out.println(fileter.getUseRate());
    		System.out.println(fileter.addIfNotExist("1111111111111"));
    	}
    	
    }

    构造布隆过滤器,指定hash函数个数k,分配bit数组,计算给定字符串K个hash函数值,将每一位置为true,不考虑误判率,只有当k位bit都为true时,才表示给定字符串已经存在。

    参考链接:

    https://www.cnblogs.com/liyulong1982/p/6013002.html

    https://blog.csdn.net/u014653197/article/details/76397037

    https://blog.csdn.net/fouy_yun/article/details/81075432

    https://segmentfault.com/a/1190000015482091

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 263,891
精华内容 105,556
关键字:

java实现过滤器

java 订阅