Java 为给定的唯一编号列表/集合/数组生成唯一id

Java 为给定的唯一编号列表/集合/数组生成唯一id,java,encryption,cryptography,wolfram-mathematica,Java,Encryption,Cryptography,Wolfram Mathematica,我的数组包含从0到integer.max value的随机唯一数 如何生成唯一的id/签名(int)来唯一地标识每个数组,而不是搜索每个数组并检查每个数字 e、 g 每个数组可以有不同的长度,但数字在数组中不重复,可以在其他数组中重复。每个数组的唯一id的目的是通过id来识别它,以便快速进行搜索。数组包含组件的id,数组的唯一签名/id将标识其中包含的组件 此外,无论数组中值的顺序如何,生成的id都应该相同。像{1,5}和{5,1}应该生成相同的id 我查找了不同的数字配对方法,但结果数字随着数

我的数组包含从0到integer.max value的随机唯一数

如何生成唯一的id/签名(int)来唯一地标识每个数组,而不是搜索每个数组并检查每个数字

e、 g

每个数组可以有不同的长度,但数字在数组中不重复,可以在其他数组中重复。每个数组的唯一id的目的是通过id来识别它,以便快速进行搜索。数组包含组件的id,数组的唯一签名/id将标识其中包含的组件

此外,无论数组中值的顺序如何,生成的id都应该相同。像{1,5}和{5,1}应该生成相同的id

我查找了不同的数字配对方法,但结果数字随着数组长度的增加而增加,达到了整数无法容纳的程度


分配给组件的ID可以调整,它们不必是整数序列,只要有一个良好的数字范围就可以。唯一的要求是,一旦为数组(组件id的集合)生成了id,它们就不应该冲突。如果该数组中的集合发生更改,则可以在运行时生成。严格来说,您要求的是不可能的:即使只有两个元素的数组,可能的数组(忽略顺序后约261个)也比可能的签名(232个)多得多。而且您的数组不限于两个元素,因此您的情况会成倍恶化


但是,如果您可以接受低重复率和错误匹配率,一种简单的方法是使用
+
运算符将所有元素相加(基本上计算模232的和)。这是java.util.Set的hashCode()方法所采用的方法。它并不能完全消除比较整个数组的需要(因为需要检测错误的匹配),但它将从根本上减少这种比较的数量(因为很少有数组会匹配任何给定的数组)。

这可以通过哈希函数
h()
和顺序规范化函数近似解决(例如
sort()
)。散列函数是有损的,因为唯一散列(2^32或2^64)的数量小于可能的可变长度整数集的数量,导致两个不同的集合具有相同ID的可能性很小(散列冲突)。通常,如果

  • 你使用了一个好的散列函数
  • 您的数据集并没有大到可笑的程度
顺序规范化函数将确保将集合{x,y}和{y,x}散列为相同的值

对于散列函数,您有许多选项,但请选择一个使冲突概率最小化的散列,例如加密散列(SHA-256,MD5)或者,如果您需要最先进的性能,请使用MurrueHash3或其他常用哈希。MurrueHash3可以生成一个整数作为输出,而加密哈希需要额外的步骤,从二进制输出中提取4或8个字节,并解压缩为整数。(使用任何一致的字节选择,例如first或last。)

在伪代码中:

int getId(setOfInts) {
    intList = convert setOfInts to integer list
    sortedIntList = sort(intList)
    ilBytes = cast sortedIntList to byte array
    hashdigest = hash(ilBytes)
    leadingBytes = extract 4 or 8 leading bytes of hashdigest
    idInt = cast leadingBytes to integer
    return idInt
}

您希望{1,5}和{5,1}具有相同的ID。这排除了标准哈希函数,在这种情况下,标准哈希函数将给出不同的结果。一个选项是在哈希之前对数组进行排序。请注意,加密哈希非常慢;您可能会发现像FNV这样的非加密哈希就足够了。它肯定会更快


为了避免排序,只需添加mod 2^32或mod 2^64的所有数字,正如@ruakh所建议的,并接受您将有一定比例的冲突。添加数组长度将避免一些冲突:{5,1}将不匹配{1,2,3},在这种情况下为(2+(5+1))!=(3+(1+2+3))。您可能希望使用实际数据进行测试,以查看这是否具有足够的优势。

发布您迄今为止尝试过的代码。您希望此id确切位置在何处?如果您希望它出现在数组中,您可以开始添加负数作为第一个数字(例如,第一个数组有-1,第二个数组有-2等等)
int getId(setOfInts) {
    intList = convert setOfInts to integer list
    sortedIntList = sort(intList)
    ilBytes = cast sortedIntList to byte array
    hashdigest = hash(ilBytes)
    leadingBytes = extract 4 or 8 leading bytes of hashdigest
    idInt = cast leadingBytes to integer
    return idInt
}