最近项目中需要实现一个IP库查询的模块,自己实现了一个算法,借鉴了一致性哈希算法的原理。
IP库的数据结构如下:
start_ip_num(long) start_ip(String) end_ip_num(long) end_ip city city_id city_cd ip_route_status update_date province
起始IP转成long型数据 起始IP 结束IP转成long型数据 结束IP 城市 省份
思路是:
1. 从数据库初始化IP地址库到内存,起始IP封装成IPData对象,包含起始IP和省市信息等;
2. 开始IP封装成long型数据作为key,IPData对象作为value,对应成key-value的Map型数据结构
3. 对key作升序排序,和IPData插入TreeMap结构集合
4. 将目标IP转化成long型数据,找出TreeMap中找出小于等于目标IP的key集合
5. 获取这个集合的最后一个key,即逆时针距离目标IP最近的一条,即目标IP所在的IP区间key
6. 根据获取到的最后一个key从Map中找到对应的IPData对象,获取省市信息
注:TreeMap的查询时间复杂度为o(logn)
package com.suning.ipRoute; /** * Created by 15061760 on 2016/3/2 0002. */ public class IPData { private long startIPNum; private long endIPNum; private String startIp; private String endIp; private String city; private String province; public long getStartIPNum() { return startIPNum; } public void setStartIPNum(long startIPNum) { this.startIPNum = startIPNum; } public long getEndIPNum() { return endIPNum; } public void setEndIPNum(long endIPNum) { this.endIPNum = endIPNum; } public String getStartIp() { return startIp; } public void setStartIp(String startIp) { this.startIp = startIp; } public String getEndIp() { return endIp; } public void setEndIp(String endIp) { this.endIp = endIp; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } @Override public String toString() { return ("<<" + this.getStartIp() + ";" + this.getEndIp() + ";" + this.getCity() + ";" + this.getProvince() + ">>"); } }package com.suning.ipRoute; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import java.util.*; /** * Created by 15061760 on 2016/3/2 0002. */ public class IPSearch { private static final String filePath = "F:\\ip_route.xml"; static final String START_IP_NUM = "start_ip_num"; static final String END_IP_NUM = "end_ip_num"; static final String START_IP = "start_ip"; static final String END_IP = "end_ip"; static final String CITY = "city"; static final String PROVINCE = "province"; static final String ip = "58.101.255.192"; static final long ip_long = 58101255192L; public static void main(String[] args) throws Exception { //读文件 SAXReader saxReader = new SAXReader(); Document doc = saxReader.read(filePath); Element root = doc.getRootElement(); Iterator<Element> it = root.elementIterator(); SortedMap<Long, IPData> sortedMap = new TreeMap<Long, IPData>(); while (it.hasNext()) { Element item = it.next(); IPData ipData = new IPData(); ipData.setStartIPNum(Long.parseLong(item.elementText(START_IP_NUM))); ipData.setEndIPNum(Long.parseLong(item.elementText(END_IP_NUM))); ipData.setStartIp(item.elementText(START_IP)); ipData.setEndIp(item.elementText(END_IP)); ipData.setCity(item.elementText(CITY)); ipData.setProvince(item.elementText(PROVINCE)); sortedMap.put(ipData.getStartIPNum(), ipData); } List<Long> ipList = new ArrayList<Long>(); Random random = new Random(); //随机生成30000条数据 for (int i = 0; i < 10; i++) { int[] ip = new int[4]; ip[0] = random.nextInt(255); ip[1] = random.nextInt(255); ip[2] = random.nextInt(255); ip[3] = random.nextInt(255); long targetIP = getIP(ip); ipList.add(targetIP); } System.out.println("========================="); long start = System.currentTimeMillis(); for (int i = 0; i < ipList.size(); i++) { long targetIP = ipList.get(i); SortedMap<Long, IPData> subMap = sortedMap.headMap(targetIP); if (subMap != null && subMap.size() > 0) { long key = subMap.lastKey(); IPData ipData = subMap.get(key); // System.out.println("目标IP:" + targetIP + ":[" + ipData.getProvince() + ";" + ipData.getCity() + "]"); } } System.out.println(System.currentTimeMillis() - start); // SortedMap<Long, IPData> subMap = sortedMap.headMap(ip_long); // long key = subMap.lastKey(); // IPData ipData = sortedMap.get(key); // long end = System.currentTimeMillis(); // System.out.println(end - start); // System.out.println(ipData.getProvince() + "----" + ipData.getCity()); } private static long getIP(int[] ip_array) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 4; i++) { if (i == 0) { sb.append(ip_array[i]); } else { if (String.valueOf(ip_array[i]).length() == 1) { sb.append("00").append(ip_array[i]); } else if (String.valueOf(ip_array[i]).length() == 2) { sb.append("0").append(ip_array[i]); } else { sb.append(ip_array[i]); } } } return Long.parseLong(sb.toString()); } }