Java 将地址映射到唯一号码

Java 将地址映射到唯一号码,java,algorithm,hash,ip-address,ipv4,Java,Algorithm,Hash,Ip Address,Ipv4,从IP地址生成唯一号码的最佳方法是什么 19.22.145.103 我本来打算对每个八位字节求和以得到唯一的数字,但看起来我可能无法为每个IP地址得到唯一的数字 Sum of each octet 19 + 22 + 145 + 103 = 289 as the unique number. 我已经知道,我们无法将IPv4映射到16位,所以冲突较少的解决方案是可以接受的。我正在寻找以下两点中提到的两种解决方案 首先,通过将其存储在32位数据类型中获得唯一编号的最佳方法是什么 其次,现在的问

从IP地址生成唯一号码的最佳方法是什么

19.22.145.103
我本来打算对每个八位字节求和以得到唯一的数字,但看起来我可能无法为每个IP地址得到唯一的数字

Sum of each octet 19 + 22 + 145 + 103 = 289 as the unique number.
我已经知道,我们无法将IPv4映射到16位,所以冲突较少的解决方案是可以接受的。我正在寻找以下两点中提到的两种解决方案

  • 首先,通过将其存储在32位数据类型中获得唯一编号的最佳方法是什么
  • 其次,现在的问题是我需要将这个唯一的数字存储在
    short
    数据类型中。因为short是16位的,所以我们可能无法将IPv4唯一地映射到short。如果我们仍然使用
    short
    数据类型,而不是像我上面使用的那样使用每个八位元的总和,那么我们还有没有其他方法可以减少冲突
我所有的IP地址都以
10开头。
如果有助于确定算法,那么冲突就会减少。

制作hash函数,然后将其剪切为short大小。例如:

(或其他一些素数) (7^19+5*22+11*145+17*103)%U短尺寸

制作hash函数,然后将其剪切为short大小。例如:

(或其他一些素数) (7^19+5*22+11*145+17*103)%U短尺寸


你的任务通常是不可能完成的。所以我会从商业领域寻找捷径


您需要映射所有IP地址吗?您可能可以跳过
127.*.*.
192.168.*.*.
。但这还不够。您需要减少到16位,这是一个全范围的摩擦:
1/2^16
~
1/64000
您的任务通常是不可能的。所以我会从商业领域寻找捷径


您需要映射所有IP地址吗?您可能可以跳过
127.*.*.
192.168.*.*.
。但这还不够。您需要减少到16位,这是整个范围内的一个摩擦:
1/2^16
~
1/64000

IPv4是4个八位字节,因此您可以使用以下方法获得唯一的映射

public static int asInt(byte[] addr) {
    return (addr[0] & 0xFF) | ((addr[1] & 0xFF) << 8)
          | ((addr[2] & 0xFF) << 16) | ((addr[3] & 0xFF) << 24);
}
public short hash(int n) {
    return (short) (n ^ (n >>> 16))
}
这将为您提供232个可能的值。如果要将其映射到16位并确保其唯一,则需要将映射存储在其他位置,例如

final Map<Integer, Short> mapping = new ConcurrentHashMap<>();
int next = 0;

public short idFor(byte[] bytes) {
    Integer i = asInt(bytes);
    return mapping.computeIfAbsent(i, x -> next++);
}
注意,16位值只能有65536个可能的唯一值

如果你想要一个简单的散列,你可以使用

public static int asInt(byte[] addr) {
    return (addr[0] & 0xFF) | ((addr[1] & 0xFF) << 8)
          | ((addr[2] & 0xFF) << 16) | ((addr[3] & 0xFF) << 24);
}
public short hash(int n) {
    return (short) (n ^ (n >>> 16))
}
您可以添加一个aggetate函数,如

public short hash(int n) {
    n *= 10191; // an odd prime of around 2^^16
    return (short) (n ^ (n >>> 16))
}
不理想的是,顶部的位不会以这种方式产生太多的随机性。您可以改为使用64位计算

public short hash(int n) {
    long n2 = n * 0x6d0f27bdL; 
    n2 ^= (n2 >>> 21) ^ (n2 >>> 42);
    return (short) (n ^ (n >>> 16) ^ (n >> 32));
}

IPv4是4个八位字节,因此您可以使用以下内容获得唯一的映射

public static int asInt(byte[] addr) {
    return (addr[0] & 0xFF) | ((addr[1] & 0xFF) << 8)
          | ((addr[2] & 0xFF) << 16) | ((addr[3] & 0xFF) << 24);
}
public short hash(int n) {
    return (short) (n ^ (n >>> 16))
}
这将为您提供232个可能的值。如果要将其映射到16位并确保其唯一,则需要将映射存储在其他位置,例如

final Map<Integer, Short> mapping = new ConcurrentHashMap<>();
int next = 0;

public short idFor(byte[] bytes) {
    Integer i = asInt(bytes);
    return mapping.computeIfAbsent(i, x -> next++);
}
注意,16位值只能有65536个可能的唯一值

如果你想要一个简单的散列,你可以使用

public static int asInt(byte[] addr) {
    return (addr[0] & 0xFF) | ((addr[1] & 0xFF) << 8)
          | ((addr[2] & 0xFF) << 16) | ((addr[3] & 0xFF) << 24);
}
public short hash(int n) {
    return (short) (n ^ (n >>> 16))
}
您可以添加一个aggetate函数,如

public short hash(int n) {
    n *= 10191; // an odd prime of around 2^^16
    return (short) (n ^ (n >>> 16))
}
不理想的是,顶部的位不会以这种方式产生太多的随机性。您可以改为使用64位计算

public short hash(int n) {
    long n2 = n * 0x6d0f27bdL; 
    n2 ^= (n2 >>> 21) ^ (n2 >>> 42);
    return (short) (n ^ (n >>> 16) ^ (n >> 32));
}

我有了一个新方法。。检查代码,它保证您的代码是唯一的

private static final int HASH_PRIME = 23;
public static short convertIP(String ip) {
    String res = "";
    for(String num: ip.split("\\.")) {
        int val = Integer.parseInt(num);
        while(val>HASH_PRIME) {
            val = val / HASH_PRIME;
        }
        if(new Random().nextInt(10) <= 4) {
            res += convertChar(val);
        } else {
            res += val;
        }
    }
    System.out.println("result = "+res); // the result could be anything like: T2264, 19WGE, TWGE, 1922G4, etc

    return (short) (res.hashCode() % Short.MAX_VALUE);
}

private static char convertChar(int num) {
    return (char)((num % 26) + 65);
}

public static void main(String[] args) {
    System.out.println(convertIP("19.22.145.103"));
    // the short code for the same IP will be unique majorly.. i.e. 24311, 23784, 31968, 16079, 23767 .. etc
}
private static final int HASH_PRIME=23;
公共静态短转换器ip(字符串ip){
字符串res=“”;
for(字符串编号:ip.split(\\)){
int val=Integer.parseInt(num);
while(val>HASH_PRIME){
val=val/HASH_素数;
}

如果(new Random().nextInt(10)我有一个新方法..检查代码,它保证您的代码是唯一的

private static final int HASH_PRIME = 23;
public static short convertIP(String ip) {
    String res = "";
    for(String num: ip.split("\\.")) {
        int val = Integer.parseInt(num);
        while(val>HASH_PRIME) {
            val = val / HASH_PRIME;
        }
        if(new Random().nextInt(10) <= 4) {
            res += convertChar(val);
        } else {
            res += val;
        }
    }
    System.out.println("result = "+res); // the result could be anything like: T2264, 19WGE, TWGE, 1922G4, etc

    return (short) (res.hashCode() % Short.MAX_VALUE);
}

private static char convertChar(int num) {
    return (char)((num % 26) + 65);
}

public static void main(String[] args) {
    System.out.println(convertIP("19.22.145.103"));
    // the short code for the same IP will be unique majorly.. i.e. 24311, 23784, 31968, 16079, 23767 .. etc
}
private static final int HASH_PRIME=23;
公共静态短转换器ip(字符串ip){
字符串res=“”;
for(字符串编号:ip.split(\\)){
int val=Integer.parseInt(num);
while(val>HASH_PRIME){
val=val/HASH_素数;
}


if(新的Random().nextInt(10)在16位数据类型中存储32位有点困难,不是吗?是的,这就是为什么我说了可以减少冲突的更好的方法。如果你在问题的顶部声明你意识到你不能唯一地从32位映射到16位,那么冲突是可以接受的,那么问题可能会更清楚。@Johndod刚刚添加的不仅冲突是可能的当从32位映射到16位时,很有可能发生冲突。对于每一个16位数字,无论您的哈希算法有多好,都有2^16个可能的冲突。或者,换句话说,对于16位哈希代码,在生成大约300个哈希代码后,冲突的可能性为50%。在1000位时,可能接近100%的IP数地址你打算用这种方法编制索引吗?在16位数据类型中存储32位有点困难,不是吗?是的,这就是为什么我说了一种更好的方法,可以减少冲突。如果你在问题的顶部说明你意识到你不能唯一地从32位映射到16位,那么冲突是可以接受的。@JohnDood刚刚补充的是,不仅当从32位映射到16位时可能发生冲突,而且很有可能发生冲突。对于每一个16位数字,都有2^16个可能的冲突,无论您的哈希算法有多好。或者,换句话说,对于16位哈希代码,在生成大约300个哈希代码后,冲突的可能性为50%。至少1000,这可能接近100%你打算用这种方法索引多少IP地址?我正要说同样的话。BSD校验和哈希算法在文章中甚至有Java代码。我不知道那个算法。我总是使用素数,我肯定会检查BSD校验和。谢谢:)我也不知道;)。我刚在谷歌上搜索了16位哈希,两次点击后就看到了文章。我的方法非常灵活,你可以随心所欲地取模。每个互质数都有你想要的素数。@Rjiuk你能举个例子吗