最近看到一则招聘的JD,附了一个算法题的链接,原题如下:

  1. 请实现一个IP白名单过滤算法,实现以下接口
  2. boolean addWhiteIpAddress(String ip);
  3. boolean isWhiteIpAddress(String ip);
  4. 要求如下:
  5. 占用空间尽量少
  6. 运算效率尽量高
  7. 在内存中完成查询及判断
  8. 接口可能被并发询问
  9. 尽量能存储整个IP地址空间
  10. 代码可运行,且包含单测
  • 思路:

        如题,需要实现的是一个白名单的功能而不是黑名单,且要求尽可能存储整个IP地址空间,所以如果直接存储ip地址的字符串32位JVM下需要约:2^32 * (32+32+ (7+15)/2) = 300GB(这里只是非常粗略的估算),当然如果把字符串换成char数组可以省下对象头和类型指针,预计需约44GB,这完全超出了32位JVM的堆空间,而且就算借助于文件系统和硬盘,这么大数据量的字符串比较效率也是非常低下的。

        所以换个思路,针对IPV4,一个IP地址为32个bit位,可以直接将IP地址转换为int类型。又因为白名单只有两种状态,要么在白名单中,要么不在,所以很自然就想到位图了,用两个BitSet即可存储全部IPV4的地址,占用512M多的内存,也支持随机访问。

  • 缺点:

    1. volatile修饰,性能会降低(修饰对象或数组,如果对象属性或数组元素被修改,可以间接保证对象属性或数组元素的线程可见性)
    2. 目前没考虑IPV6
    3. 测试的数据量不够,可能有些边界还没考虑到,还没做性能测试
  1. import java.util.BitSet;
  2. import org.junit.Test;
  3. import org.springframework.util.Assert;
  4. import org.springframework.util.StringUtils;
  5. public class IPFiliterTest {
  6. // Java语言中没有无符号整形,int的最大值只能表示到0x7fffffff,所以需要两个BitSet来存储高低位
  7. private static volatile BitSet low = new BitSet(Integer.MAX_VALUE);
  8. private static volatile BitSet high = new BitSet(Integer.MAX_VALUE);
  9. /**
  10. * 固定8位,前面不足的补零
  11. * @param num
  12. * @return
  13. */
  14. private static String getByteBinaryStr(int num) {
  15. StringBuilder sb = new StringBuilder();
  16. for (int i = 0; i < 8; i++) {
  17. if ((num & 1) == 1) {
  18. sb.append(1);
  19. } else {
  20. sb.append(0);
  21. }
  22. num = num >> 1;
  23. }
  24. return sb.reverse().toString();
  25. }
  26. /**
  27. * 将IP地址字符串转换为int
  28. * @param ip
  29. * @return
  30. */
  31. private static int chgIpStrToInt(String ip) {
  32. if (ip == null || StringUtils.isEmpty(ip)) {
  33. throw new RuntimeException("Null string");
  34. }
  35. String[] arr = ip.split("\\.");
  36. if (arr == null || arr.length != 4) {
  37. throw new RuntimeException("Invalid ip");
  38. }
  39. if ("128.0.0.0".equals(ip)) {
  40. return Integer.MIN_VALUE;
  41. }
  42. StringBuilder sb = new StringBuilder();
  43. sb.append(getByteBinaryStr(new Integer(arr[0])));
  44. sb.append(getByteBinaryStr(new Integer(arr[1])));
  45. sb.append(getByteBinaryStr(new Integer(arr[2])));
  46. sb.append(getByteBinaryStr(new Integer(arr[3])));
  47. String intStr = sb.toString();
  48. // Integer.valueOf处理负数会有问题
  49. if (intStr.charAt(0) == '1') {
  50. char[] chars = intStr.toCharArray();
  51. chars[0] = '0';
  52. intStr = new String(chars);
  53. return 0 - Integer.valueOf(intStr, 2).intValue();
  54. }
  55. return Integer.valueOf(intStr, 2).intValue();
  56. }
  57. public static boolean addWhiteIpAddress(String ip){
  58. int ipInt = chgIpStrToInt(ip);
  59. if (ipInt < 0) {
  60. high.set(ipInt+Integer.MAX_VALUE+1);
  61. } else {
  62. low.set(ipInt);
  63. }
  64. return true;
  65. }
  66. public static boolean isWhiteIpAddress(String ip) {
  67. int ipInt = chgIpStrToInt(ip);
  68. if (ipInt < 0) {
  69. return high.get(ipInt+Integer.MAX_VALUE+1);
  70. } else {
  71. return low.get(ipInt);
  72. }
  73. }
  74. @Test
  75. public void test() throws InterruptedException {
  76. String ip1= "0.0.0.0";
  77. addWhiteIpAddress(ip1);
  78. Assert.isTrue(isWhiteIpAddress(ip1));
  79. String ip2= "127.0.0.1";
  80. addWhiteIpAddress(ip2);
  81. Assert.isTrue(isWhiteIpAddress(ip2));
  82. String ip3= "255.255.255.255";
  83. addWhiteIpAddress(ip3);
  84. Assert.isTrue(isWhiteIpAddress(ip3));
  85. String ip4= "128.0.0.0";
  86. addWhiteIpAddress(ip4);
  87. Assert.isTrue(isWhiteIpAddress(ip4));
  88. Assert.isTrue(!isWhiteIpAddress("0.0.0.1"));
  89. Assert.isTrue(!isWhiteIpAddress("1.1.1.1"));
  90. Assert.isTrue(!isWhiteIpAddress("001.001.001.001"));
  91. }
  92. }

算法题:实现一个IP白名单过滤器的更多相关文章

  1. 如何为ASP.NET Core设置客户端IP白名单验证

    原文链接:Client IP safelist for ASP.NET Core 作者:Damien Bowden and Tom Dykstra 译者:Lamond Lu 本篇博文中展示了如何在AS ...

  2. Windows Azure Web Site (14) Azure Web Site IP白名单

    <Windows Azure Platform 系列文章目录> 我们知道,在Azure Cloud Service和Virtual Machine,可以通过Endpoint ACL (Ac ...

  3. IP白名单的实现(PHP)

    有些项目可能会用到一个IP地址的白名单黑名单之类的验证. 比如,只有IP地址在白名单中,才可以访问该系统. 那么此时,白名单的维护,一般是一个文件,里边是一些IP地址(每行一个IP),当然也有的可能是 ...

  4. 对actuator的管理端点进行ip白名单限制(springBoot添加filter)

    在我们的SpringCloud应用中,我们会引入actuator来进行管理和监控我们的应用 常见的有:http://www.cnblogs.com/yangzhilong/p/8378152.html ...

  5. Java IP白名单相关工具类

    关于设置IP白名单相关的一些方法,整理,记录了一下. package com.tools.iptool; import java.util.ArrayList; import java.util.Ha ...

  6. Data Lake Analytics IP白名单设置攻略

    当我们成功开通了 DLA 服务之后,第一个最想要做的事情就是登录 DLA 数据库.而登录数据库就需要一个连接串.下面这个页面是我们首次开通 DLA 之后的界面,在这里我们要创建一个服务访问点. 在上面 ...

  7. 嵌入式Linux可用的防火墙——iptables:实现ip白名单、mac地址白名单

    iptables是linux系统下的一个功能强大的模块,不仅可以用作防火墙,还可以实现NAT等众多路由功能.iptables的容器有很清晰的层次关系: 1. iptables是表的容器,iptable ...

  8. 利用CentOS系统IPtables防火墙添加网站IP白名单

    参考博文: 利用CentOS系统IPtables防火墙添加360网站卫士节点IP白名单 centos6.5添加白名单如下: 在防火墙 配置文件中加入白名单  ip -A INPUT -s 183.13 ...

  9. 解决微信公众平台IP白名单

    微信公众平台,作为自媒体的旗舰级产品,越来越多的人已经投入它的怀抱.正如它的广告词所说:再小的个体,也有品牌 好吧,闲话不多说,今天要说的是它的IP白名单机制. 我们现在安装的大部分的电信的家庭级别的 ...

随机推荐

  1. js继承之组合继承(结合原型链继承 和 借用构造函数继承)

    在我的前两篇文章中,我们已经介绍了 js 中实现继承的两种模式:原型链继承和借用构造函数继承.这两种模式都存在各自的缺点,所以,我们考虑是否能将这二者结合到一起,从而发挥二者之长.即在继承过程中,既可 ...

  2. Supervisor守护DotNet Core控制台程序

    Supervisor 相信对Linux系统很熟的都知道这个软件,基于Python写的一个守护进程软件.具体的介绍和使用我就不再赘述了. 使用asp.net core 部署在Linux常用的方法 我们可 ...

  3. CentOS7搭建本地YUM仓库,并定期同步阿里云源

    CentOS7同步阿里云镜像rpm包并自建本地yum仓库 系统环境 # cat /etc/centos-release CentOS Linux release 7.6.1810 (Core) # u ...

  4. 从壹开始微服务 [ DDD ] 之九 ║从军事故事中,明白领域命令验证(上)

    烽烟 哈喽大家周二好呀,咱们又见面了,上周末掐指一算,距离 圣诞节 只有 5 周的时间了(如果你还不知道为啥我要提圣诞节这个时间点,可以看看我的第二系列开篇<之一 ║ D3模式设计初探 与 我的 ...

  5. 排序算法——(2)Python实现十大常用排序算法

    上期为大家讲解了排序算法常见的几个概念: 相关性:排序时是否需要比较元素 稳定性:相同元素排序后是否可能打乱 时间空间复杂度:随着元素增加时间和空间随之变化的函数 如果有遗忘的同学可以看排序算法——( ...

  6. :Android网络编程--XML之解析方式:SAX

    任何放置在资源(res)目录下的内容可以通过应用程序的R类访问,这是被Android编译过的,而任何放置在资产(assets)目录下的内容会保持它的原始文件格式,为了读取它们,必须使用AssetMan ...

  7. gorm的日志模块源码解析

    gorm的日志模块源码解析 如何让gorm的日志按照我的格式进行输出 这个问题是<如何为gorm日志加traceId>之后,一个群里的朋友问我的.如何让gorm的sql日志不打印到控制台, ...

  8. 使用vue开发项目需要注意的问题和可能踩到的坑

    最近,在公司给一些刚刚使用vue进行开发的同学做了一次分享, 其中包括一些vue开发中需要注意的点, 以及一些可能会踩到的坑.具体内容如下: 一.生命钩子使用需要注意的地方 1.beforeCreat ...

  9. Java开发必须掌握的线上问题排查命令

    作为一个合格的开发人员,不仅要能写得一手还代码,还有一项很重要的技能就是排查问题.这里提到的排查问题不仅仅是在coding的过程中debug等,还包括的就是线上问题的排查.由于在生产环境中,一般没办法 ...

  10. Flutter 实现原理及在马蜂窝的跨平台开发实践

    一直以来,跨平台开发都是困扰移动客户端开发的难题. 在马蜂窝旅游 App 很多业务场景里,我们尝试过一些主流的跨平台开发解决方案, 比如 WebView 和 React Native,来提升开发效率和 ...