java的TreeMap在ip转区域的使用

来源:互联网 发布:数据库系统的构成 编辑:程序博客网 时间:2024/04/30 15:12

前段时间 有个统计的需求,有用户的登陆IP,想转成市,然后用于统计。几百万的数据拿来网上查还是慢了些,于是就找一些批量,或者本地的处理方法

有两个方案是备选的:

一、
这边的一个同事提供了一个文件(不清楚哪里搞来的),里面有ipbegin-ipEnd 地市,省 这些字段,用了10来个ip 测试,还是靠谱,格式如下

1551@@1.189.24.0@@1.189.24.255@@黑龙江省哈尔滨市通河县@@联通@@黑龙江省@@哈尔滨市@@HL1561@@1.189.247.0@@1.189.248.255@@黑龙江省哈尔滨市延寿县@@联通@@黑龙江省@@哈尔滨市@@HL1571@@1.189.249.0@@1.189.250.255@@黑龙江省哈尔滨市双城区@@联通@@黑龙江省@@哈尔滨市@@HL1581@@1.189.25.0@@1.189.30.255@@黑龙江省哈尔滨市@@联通@@黑龙江省@@哈尔滨市@@HL1591@@1.189.251.0@@1.189.254.255@@黑龙江省哈尔滨市@@联通@@黑龙江省@@哈尔滨市@@HL

二、
http://www.ipip.net这个地址,有ip库下载,也提供了各语言的api例子.

后来考虑了下,第一个方案,数据都是现成的,比较有安全感,就选择自己去解析。

具体处理

整个文件有40W行数据,用循环查找是太慢了,考虑到ip有大小之分,于是决定用树.

设计思路

一条数据一个节点,利用大小比较, 构建成平衡树,查找的时候,一个 ip,如果小于ip_begin,则往一个方向,如果大于ip_end 则另一方向,如果在begin和end中间,则此节点为目标节点.

程序设计

java里面有treeMap,把节点扔进去,其自己会构建成一棵树,当然,此节点要实现 compareTo
的方法,把节点和ip的大小比较出来.
除了ip_begin,和ip_end , 此entity 上也加上 targetip用于通过ip取节点时的比较

具体代码

两个类是核心的

  • TipRange
    compareTo方法是关键
public class TipRange implements Comparable<TipRange> {    private Integer id;    // ipBegin    private String ipBegin;    // ipEnd    private String ipEnd;    private String regiondesc;    private String typedesc;    private String province;    private String city;    private String provinceCode;    private Date updatetime;    private String targetip;    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public String getIpBegin() {        return ipBegin;    }    public void setIpBegin(String ipBegin) {        this.ipBegin = ipBegin;    }    public String getIpEnd() {        return ipEnd;    }    public void setIpEnd(String ipEnd) {        this.ipEnd = ipEnd;    }    public String getRegiondesc() {        return regiondesc;    }    public void setRegiondesc(String regiondesc) {        this.regiondesc = regiondesc;    }    public String getTypedesc() {        return typedesc;    }    public void setTypedesc(String typedesc) {        this.typedesc = typedesc;    }    public String getProvince() {        return province;    }    public void setProvince(String province) {        this.province = province;    }    public String getCity() {        return city;    }    public void setCity(String city) {        this.city = city;    }    public String getProvinceCode() {        return provinceCode;    }    public void setProvinceCode(String provinceCode) {        this.provinceCode = provinceCode;    }    public Date getUpdatetime() {        return updatetime;    }    public void setUpdatetime(Date updatetime) {        this.updatetime = updatetime;    }    public String getTargetip() {        return targetip;    }    public void setTargetip(String targetip) {        this.targetip = targetip;    }    @Override    public int compareTo(TipRange targetRange) {        String paramIp = targetRange.getTargetip();        if(StringUtils.isEmpty(paramIp)&&StringUtils.isEmpty(this.getTargetip())){            //两个都没ip为空,说明range和range对比            long currtntipbeginLong = IpRangeUtil.ipStrToLong(ipBegin);            long currentipendLong = IpRangeUtil.ipStrToLong(ipEnd);            long rangeBegin = IpRangeUtil.ipStrToLong(targetRange.getIpBegin());            if(rangeBegin<currtntipbeginLong){                return 1;            }else if (rangeBegin==currtntipbeginLong){                return 0;            }else{                return -1;            }        }        if(StringUtils.isNotEmpty(paramIp)&&StringUtils.isEmpty(this.getTargetip())){            ////两个都没ip为空,说明range和range对比            long targetIpLong = IpRangeUtil.ipStrToLong(paramIp);            long currtntipbeginLong = IpRangeUtil.ipStrToLong(ipBegin);            long currentipendLong = IpRangeUtil.ipStrToLong(ipEnd);            //判断目标要往哪走            if(targetIpLong<currtntipbeginLong){                return 1;            }else if (targetIpLong>currentipendLong){                return -1;            }else{                return 0;            }        }        if(StringUtils.isEmpty(paramIp)&&StringUtils.isNotEmpty(this.getTargetip())){            //两个都没ip为空,说明range和range对比            long currentIpLong = IpRangeUtil.ipStrToLong(this.getTargetip());            long targetBeginLong = IpRangeUtil.ipStrToLong(targetRange.getIpBegin());            long targetEndLong = IpRangeUtil.ipStrToLong(targetRange.getIpEnd());            //判断目标要往哪走            if(currentIpLong<targetBeginLong){                return -1;            }else if (currentIpLong>targetEndLong){                return 1;            }else{                return 0;            }        }        return -2;    }}
  • TgipRangeServiceImpl
    取数据,扔到treemap,其 ipToAddress 方法即为 暴露的api
import com.yp.springboot.util.FileReadUtils;import com.yp.springboot.util.IFileOperByLine;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.core.RowMapper;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import java.io.File;import java.sql.Date;import java.sql.ResultSet;import java.sql.SQLException;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.TreeMap;@Servicepublic class TgipRangeServiceImpl {private static Map<TipRange, TipRange> cacheIpRangeMap;@Autowired public JdbcTemplate jdbcTemplate;private static Logger logger = LoggerFactory.getLogger("rlog");public List<TipRange> queryAllByFile() throws Exception{File file = new File("E:\\codeplace\\n_learn\\java\\springboot\\myexample\\springbootweb\\src\\main\\resources\\regionip.txt");// final List<TipRange> iprangeList1 = new ArrayList();FileReadUtils.readFileAndUnionObj(file, new IFileOperByLine() {@Override public void toOperLineNoList(String fileName, String linestr) {String[] arrayText = linestr.split("@@");Integer id = Integer.valueOf(arrayText[0]);String ipBegin = arrayText[1];String ipEnd = arrayText[2];String regiondesc = arrayText[3];String typedesc = arrayText[4];String province = arrayText[5];String city = arrayText[6];String provinceCode = arrayText[7];TipRange tmp = new TipRange();tmp.setId(id);tmp.setIpBegin(ipBegin);tmp.setIpEnd(ipEnd);tmp.setRegiondesc(regiondesc);tmp.setTypedesc(typedesc);tmp.setProvince(province);tmp.setCity(city);tmp.setProvinceCode(provinceCode);//处理 iprangeList1.add(tmp);}});return iprangeList1;}/** * * @return */ @Transactional(propagation = Propagation.NOT_SUPPORTED)protected Map<TipRange, TipRange> genIpRangeToLogAllMap() throws Exception {Map<TipRange, TipRange> allMap = new TreeMap<TipRange, TipRange>();List<TipRange> allList = queryAllByFile();for (TipRange entityRange : allList) {allMap.put(entityRange, entityRange);}return allMap;}private String toTrim(String sstr){if(sstr==null)return "";return sstr.trim();}@Transactional(propagation = Propagation.NOT_SUPPORTED)private synchronized void initMap() throws Exception {cacheIpRangeMap = genIpRangeToLogAllMap();}/* */ @Transactional(propagation = Propagation.NOT_SUPPORTED)public TipRange ipToAddress(String ip) throws Exception {synchronized (this) {if (cacheIpRangeMap == null) {initMap();}}TipRange tmp = new TipRange();tmp.setTargetip(ip);return cacheIpRangeMap.get(tmp);}}

说明:

代码 :https://github.com/huawumingguo/springbootsample/tree/master/springbootweb

0 0
原创粉丝点击