Java 将IP地址范围映射到国家代码(数据结构哈希映射或树?)

Java 将IP地址范围映射到国家代码(数据结构哈希映射或树?),java,tree,hashtable,Java,Tree,Hashtable,试图解决我在这里发现的一个难题: 目标是在内存中重新显示IP地址范围到国家代码的查找表,并使用此数据结构来处理IP地址的所有行,以识别国家代码 所以我从一开始就想到使用HashTable 哈希表非常有效;如果我们有一个国家代码范围查找,因为我们有较少的国家名称映射到ip地址范围 但不确定;如何使用国家/地区代码的IP地址。有什么想法吗? 或者我可以使用树数据结构吗?输入文件提供一系列IP地址(不是1:1映射),因此您需要某种有序映射结构 // Assuming IPv4, and the in

试图解决我在这里发现的一个难题:

目标是在内存中重新显示IP地址范围到国家代码的查找表,并使用此数据结构来处理IP地址的所有行,以识别国家代码

所以我从一开始就想到使用HashTable 哈希表非常有效;如果我们有一个国家代码范围查找,因为我们有较少的国家名称映射到ip地址范围

但不确定;如何使用国家/地区代码的IP地址。有什么想法吗?
或者我可以使用树数据结构吗?

输入文件提供一系列IP地址(不是1:1映射),因此您需要某种有序映射结构

// Assuming IPv4, and the inputs are valid (start before end) 
// and no overlapping ranges. 
public class CountyCodeToIPMap {
    private final TreeMap<Long, CountryCodeEntry> ipMap = 
            new TreeMap<Long, CountryCodeEntry>();

    public void addIpRange(long startIp, long endIp, String countryCode) {
        ipMap.put(startIp, new CountryCodeEntry(endIp, countryCode);
    }

    public String getCountryCode(long ip) {
        Map.Entry<Long, CountryCodeEntry> entry = ipMap.floorEntry(ip);
        if (entry != null && ip <= entry.getValue().endIpAddress) {
            return entry.getValue().countryCode;
        } else {
            return null;
        }
    }
}

public class CountryCodeEntry {
    public final long endIpAddress;
    public final String countryCode;
    public CountryCodeEntry (long endIpAddress, String countryCode) {
        this.endIpAddress = endIpAdddress;
        this.countryCode = countryCode;
    }
}
//假设为IPv4,且输入有效(在结束之前开始)
//没有重叠的范围。
公共类CountyCodeToIPMap{
专用最终树映射ipMap=
新树映射();
public void addIpRange(长startIp、长endIp、字符串countryCode){
ipMap.put(startIp,新的CountryCodeEntry(endIp,countryCode);
}
公共字符串getCountryCode(长ip){
Map.Entry=ipMap.floorEntry(ip);

如果(entry!=null&&ip您没有机会存储所有ip地址。 您可以做的是存储ip地址范围所在的间隔开始结束


有一个专门的数据结构,名为,允许您查询此数据结构。

如果您正在考虑sql解决方案,这就是:

如果您可以向数据集添加一些约束,您可以使用非常简单的sql。您甚至可以使用简单的索引。-当您使用数据集时就是这样

如果您的ip块不重叠,您可以将它们作为无符号的32位数字插入数据库中的“块”表中,并像使用hibernate一样查询它们:

     (GeoipBlocks) getSession()
            .createQuery("select  gb" +
                    " from GeoipBlocks gb" +
                    " where gb.startIpNum <= :ipnumeric " +
                    " order by gb.startIpNum desc").
                    setMaxResults(1)
            .setParameter("ipnumeric", ipInLongValue)
            .uniqueResult()
(GeoipBlocks)getSession()
.createQuery(“选择gb”+
“来自GeoIPGB”+

“其中gb.startIpNum由于internet路由的工作方式,您的算法需要处理最长前缀匹配,并且您需要存储,而不是地址

我开发了一个算法来处理这个问题,但不能在这里发布。在开源中最接近的是Linux中的路由表处理代码


您还可以查看算法。这些算法可以用来解决这个问题。

存储的范围与OP说的不一样吗?尝试了20万条记录;速度很快:-),顺便问一下,Java集合中是否有编程api可以了解树数据结构属性,如“深度”或“高度”“?据我所知没有。JDK中的TreeMap是一个红黑树,因此它将大致平衡,JDK中的另一个选项是ConcurrentSkipList,如果导入数据提前排序,它将更平衡。除此之外,您需要查看Java Collections库之外的一些更专业的结构。
    select * from blocks where ipstart <= ip and ipend >= ip