java实现二分查找IP 返回指定的code

本文介绍了一个使用Java实现的二分查找算法,该算法用于在IP数据集中快速定位并返回指定的code。通过提供的测试数据链接,读者可以下载数据进行实践和验证算法的效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package Test;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;

/**
 * @Author: lsp
 * @Date: 2018/12/7 17:53
 * @Description:
 */
public class IPUtil {
    /**
     * ip地址转成long型数字
     * 将IP地址转化成整数的方法如下:
     * 1、通过String的split方法按.分隔得到4个长度的数组
     * 2、通过左移位操作(<<)给每一段的数字加权,第一段的权为2的24次方,第二段的权为2的16次方,第三段的权为2的8次方,最后一段的权为1
     *
     * @param strIp
     * @return
     */
    public static long ipToLong(String strIp) {
        String[] ip = strIp.split("\\.");
        return (Long.parseLong(ip[0]) << 24) + (Long.parseLong(ip[1]) << 16) + (Long.parseLong(ip[2]) << 8) + Long.parseLong(ip[3]);
    }

    /**
     * 将十进制整数形式转换成127.0.0.1形式的ip地址
     * 将整数形式的IP地址转化成字符串的方法如下:
     * 1、将整数值进行右移位操作(>>>),右移24位,右移时高位补0,得到的数字即为第一段IP。
     * 2、通过与操作符(&)将整数值的高8位设为0,再右移16位,得到的数字即为第二段IP。
     * 3、通过与操作符吧整数值的高16位设为0,再右移8位,得到的数字即为第三段IP。
     * 4、通过与操作符吧整数值的高24位设为0,得到的数字即为第四段IP。
     *
     * @param longIp
     * @return
     */
    public static String longToIP(long longIp) {
        StringBuffer sb = new StringBuffer();
        // 直接右移24位
        sb.append((longIp >>> 24));
        sb.append(".");
        // 将高8位置0,然后右移16位
        sb.append(((longIp & 0x00FFFFFF) >>> 16));
        sb.append(".");
        // 将高16位置0,然后右移8位
        sb.append(((longIp & 0x0000FFFF) >>> 8));
        sb.append(".");
        // 将高24位置0
        sb.append((longIp & 0x000000FF));
        return sb.toString();
    }

    //    public static void main(String[] args) {
//        System.out.println(ipToLong("219.239.110.138"));
//        System.out.println(longToIP(18537472));
//    }
    static class IPBean {
        private long begin;
        private long end;
        private String code;

        public IPBean() {
        }

        public IPBean(long begin, long end, String code) {
            this.begin = begin;
            this.end = end;
            this.code = code;
        }


        public long getBegin() {
            return begin;
        }

        public void setBegin(long begin) {
            this.begin = begin;
        }

        public long getEnd() {
            return end;
        }

        public void setEnd(long end) {
            this.end = end;
        }

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        @Override
        public String toString() {
            return "IPBean [begin=" + begin + ", end=" + end + ", code=" + code + "]";
        }

        public static class TestHalf {
            /**
             * 根据ip地址判断属于哪个ip地址段,返回这个段的ip地址对象
             * 使用顺序查找来实现
             */
            public static IPBean getIP(String ip) {
                IPBean[] ipBeans = getIpBeans();
                if (ipBeans == null || ipBeans.length == 0)
                    return null;
                long iplong = IPUtil.ipToLong(ip);
                if (iplong < ipBeans[0].getBegin() || iplong > ipBeans[ipBeans.length - 1].getEnd())
                    return null;
                for (IPBean ipBean : ipBeans) {
                    if (ipBean.getBegin() <= iplong && ipBean.getEnd() >= iplong)
                        return ipBean;
                }
                return null;
            }

            /**
             * 根据ip地址判断属于哪个ip地址段,返回这个段的ip地址对象
             * 使用二分查找算法来实现
             *
             * @param ip
             * @return
             */
            public static IPBean getIPByHalf(String ip) {
                IPBean[] ipBeans = getIpBeans();
                if (ipBeans == null || ipBeans.length == 0)
                    return null;
                long iplong = IPUtil.ipToLong(ip);
                if (iplong < ipBeans[0].getBegin() || iplong > ipBeans[ipBeans.length - 1].getEnd())
                    return null;
                int left = 0;
                int right = ipBeans.length - 1;
                int mid = (left + right) / 2;
                while (left <= right) {
                    if (iplong < ipBeans[mid].getBegin())
                        right = mid - 1;
                    if (iplong > ipBeans[mid].getBegin())
                        left = mid + 1;
                    if (iplong >= ipBeans[mid].getBegin() && iplong <= ipBeans[mid].getEnd())
                        return ipBeans[mid];
                    mid = (left + right) / 2;
                }
                return null;
            }

            /**
             * 读取ipcode.txt文件,按行读取,并转成IPBean对象数组
             *
             * @return
             */
            public static IPBean[] getIpBeans() {
                InputStreamReader inputStreamReader = null;
                BufferedReader reader = null;
                try {
                    File file = new File(TestHalf.class.getResource("/iprule").getPath());
                    inputStreamReader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
                    reader = new BufferedReader(inputStreamReader);
                    String line;
                    LinkedList<IPBean> ipBeanList = new LinkedList<IPBean>();
                    while ((line = reader.readLine()) != null) {
                        String[] tmp = line.split(",");
                        ipBeanList.add(new IPBean(IPUtil.ipToLong(tmp[0]), IPUtil.ipToLong(tmp[1]), tmp[2]));
                    }
                    IPBean[] ipBeans = ipBeanList.toArray(new IPBean[]{});
                    return ipBeans;
                } catch (Exception ex) {
                    ex.printStackTrace();
                } finally {
                    try {
                        reader.close();
                        inputStreamReader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                return null;
            }
        }
    }
}




测试类:

public class Test {
    public static void main(String[] args) {
        IPUtil.IPBean ipBean = getIPByHalf("20.1.1.255");
        IPUtil.IPBean ipBean1 = getIP("20.1.1.255");
        System.out.println(ipBean);
        System.out.println(ipBean1);
    }
}

测试数据下载地址:https://download.youkuaiyun.com/download/qq_38202756/10835921

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值