放翁(文初)的一畝三分地

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            210 隨筆 :: 1 文章 :: 320 評論 :: 0 Trackbacks
              下面是一段簡單的判斷一個ip是否在一組ip中的函數(shù),其中ip和ip組的表達方式可以為這樣(ip="192.3.22.34",iplist="123.21.23.11,121.2.11.234,12.*.23.*"),下面紅色部分是開始一個同學(xué)寫的,藍色部分是后來我嘗試修改的。要說明的就以下幾點:
               1.很多時候優(yōu)化可以在海量運算之前做好準備,例如分析的數(shù)據(jù)先做預(yù)處理,因為往往可讀性和計算效率會有沖突。
               2.如果沒有緩存,那么構(gòu)建利于高效計算的代價可能超出簡單但計算效率一般的情況。
               3.在數(shù)據(jù)量很大的情況下,如何節(jié)省存儲直接決定你是否能夠緩存這些數(shù)據(jù)用于下次計算。

              有興趣的同學(xué)可以執(zhí)行以下下面一些代碼(拷貝到eclipse格式化看和執(zhí)行比較好):
              改動的主要內(nèi)容在于對數(shù)據(jù)作預(yù)處理時增加了一點轉(zhuǎn)換,6位byte作為支持ipv6的存儲,第7位作為標(biāo)識位來便于避免不需要的比對。
              用到了org.apache.commons.lang.StringUtils,它的split方法就是采用簡單的substring而不是pattern,效率很高,特別對于海量計算。

             具體的測試代碼:
             public static void  main(String[] args)
           {
            long beg = System.currentTimeMillis();
            
            //下面這些代碼是用于存粹比較計算時,對白名單做預(yù)編譯和緩存
            byte[][] whiteIps = prepare("12.24.23.123,12.25.23.255,12.24.23.17,*.25.*.*,12.24.*.*");
            
            String[] allowIps = StringUtils.split("12.24.23.123,12.25.23.255,12.24.23.17,*.25.*.*,12.24.*.*",",");
            List<String[]> whiteIps2 = new ArrayList<String[]>();
            if (null != allowIps && allowIps.length > 0) {
             for (int i = 0; i < allowIps.length; i++) {
              //把每個ip按“.”拆開,得到一個四位的數(shù)組
              String[] ipParse = StringUtils.split(allowIps[i], ".");
              whiteIps2.add(ipParse);
             }
            }
            
            for(int i = 0 ; i < 1000000 ; i++)
            {
             //第一組對比,增加了多一點的預(yù)處理,性能下降
             //checkAppIpWhite("12.24.23.123,12.25.23.255,12.24.23.17,*.25.*.*,12.24.*.*","12.24.23.19");
             //checkAppIpWhite("12.24.23.123,12.25.23.255,12.24.23.17,*.25.*.*,12.24.*.*","12.24.23.11");
             //checkAppIpWhiteV2("12.24.23.123,12.25.23.255,12.24.23.17,*.25.*.*,12.24.*.*","12.24.23.19");
             //checkAppIpWhiteV2("12.24.23.123,12.25.23.255,12.24.23.17,*.25.*.*,12.24.*.*","12.24.23.11");
             
             //存粹的比較計算,性能上升
          //   checkAppIpWhite(whiteIps2,"12.24.23.19");
          //   checkAppIpWhite(whiteIps2,"12.24.23.11");  
             checkAppIpWhiteV2(whiteIps,"12.24.23.19");
             checkAppIpWhiteV2(whiteIps,"12.24.23.11");
            }
            
            System.out.println("end test : " +  (System.currentTimeMillis() - beg));
           }


          老的比較代碼函數(shù)如下:
          public static boolean checkAppIpWhite(String ipWhilte,String remoteIp){
            if(StringUtils.isEmpty(ipWhilte) || StringUtils.isEmpty(remoteIp)){
             return true;
            }
            String[] allowIps = StringUtils.split(ipWhilte,",");
            List<String[]> whiteIps = new ArrayList<String[]>();
            if (null != allowIps && allowIps.length > 0) {
             for (int i = 0; i < allowIps.length; i++) {
              //把每個ip按“.”拆開,得到一個四位的數(shù)組
              String[] ipParse = StringUtils.split(allowIps[i], ".");
              whiteIps.add(ipParse);
             }
            }
            String[] requestParse = StringUtils.split(remoteIp, ".");
            for (String[] whiteIp : whiteIps) {
             if (ipsEqual(requestParse, whiteIp)) {
              return true;
             }
            }
            return false;
           }
           
           public static boolean checkAppIpWhite(List<String[]> whiteIps,String remoteIp){
            String[] requestParse = StringUtils.split(remoteIp, ".");
            for (String[] whiteIp : whiteIps) {
             if (ipsEqual(requestParse, whiteIp)) {
              return true;
             }
            }
            return false;
           }
           
           //判斷兩個ip是否相等
           public static boolean ipsEqual(String[] requestIp, String[] whiteIp) {
            boolean equal = false;
            
            //判斷白名單ip是否在列表中必須要兩個ip都不為空進行比較
            if (requestIp != null && whiteIp != null && requestIp.length == whiteIp.length) {   
             if (requestIp[0].equals(whiteIp[0])
               && requestIp[1].equals(whiteIp[1])
               && ("*".equals(whiteIp[2]) || requestIp[2]
                 .equals(whiteIp[2]))
               && ("*".equals(whiteIp[3]) || requestIp[3]
                 .equals(whiteIp[3]))) {
              equal = true;
             }
            }
            
            return equal;
           }

              

          新的代碼:
          public static boolean checkAppIpWhiteV2(String ipWhite,String remoteIp){
            
            if(StringUtils.isEmpty(ipWhite) || StringUtils.isEmpty(remoteIp)){
             return true;
            }
            
            byte[][] whiteIps = prepare(ipWhite);
            
            byte[] rIp = convertIp2Bytes(remoteIp);
            
            return isInclude(whiteIps,rIp);
            
           }
           
           public static boolean checkAppIpWhiteV2(byte[][] whiteIps,String remoteIp)
           {
            byte[] rIp = convertIp2Bytes(remoteIp);
            
            return isInclude(whiteIps,rIp);
           }
           
           public static  boolean isInclude(byte[][] whiteIps,byte[] rIp)
           {
            boolean result = false;
            
            for(byte[] whiteIp : whiteIps)
            {
             for(int i = 1; i < 7; i++)
             {
              byte n = (byte)(1 << (i-1));
              
              if ((whiteIp[0] & n) != n)
              {
               if (i == 6)
                return true;
               else
                continue;
              }
              else
              {
               if (whiteIp[i] != rIp[i-1])
                break;
              }
              
              
              if (i == 6)
              {
               return true;
              }
             }
            }
            
            return result;
           }
           
           public static byte[] convertIp2Bytes(String remoteIp)
           {
            byte[] result = new byte[6];
            
            String[] points = StringUtils.split(remoteIp,".");
            
            int cursor = 0;
            
            for(String point : points)
            {
             int i = Integer.parseInt(point);
             
             if (i > Byte.MAX_VALUE)
              result[cursor] = (byte)(i - Byte.MAX_VALUE);
             else
              result[cursor] = (byte)i; 
             
             cursor += 1;
            }
            
            return result;
           }
           
           public static byte[][] prepare(String ipWhite)
           {
            String[] allowIps = StringUtils.split(ipWhite,",");//性能很好
            byte[][] result = new byte[allowIps.length][7];
            
            int cursorX = 0;
            
            for(String allowIp : allowIps)
            {
             String[] points = StringUtils.split(allowIp,".");
             
             int cursorY = 0;
             byte checkbits = 0;
             
             for(String point : points)
             {
              if (!point.equals("*"))
              {
               checkbits += 1 << cursorY;
               
               int i = Integer.parseInt(point);
               
               if (i > Byte.MAX_VALUE)
                result[cursorX][cursorY + 1] = (byte)(i - Byte.MAX_VALUE);
               else
                result[cursorX][cursorY + 1] = (byte)i; 
              }
              cursorY += 1;
             }
             
             result[cursorX][0] = checkbits;
             cursorX += 1;
            }
            
            return result;
            
           }
             
          posted on 2011-04-13 23:11 岑文初 閱讀(4604) 評論(1)  編輯  收藏

          評論

          # re: 一段代碼,幾句話 2011-04-28 10:46 北京王錚
          這個還可以再進一步優(yōu)化下吧  回復(fù)  更多評論
            


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 郯城县| 赤城县| 西藏| 中牟县| 清新县| 阳信县| 长春市| 五家渠市| 徐闻县| 安平县| 文山县| 上林县| 阿克陶县| 栾川县| 涞水县| 荣昌县| 且末县| 邵武市| 福泉市| 吴旗县| 桐庐县| 新建县| 淮南市| 靖宇县| 南平市| 德清县| 娄烦县| 藁城市| 专栏| 陇南市| 平乐县| 东港市| 都安| 金秀| 射阳县| 西宁市| 云霄县| 普定县| 丰县| 外汇| 衡南县|