如何在Java中为Map创建唯一标识符?

3

我正在寻求一种正确的方法,根据地图的内容创建唯一ID。因此,我期望包含相同数据的2个地图的ID也是相同的,并且碰撞的可能性尽可能小。

我目前的猜测是使用UUID,将地图写入对象,然后从字节构建UUID。

 Map map;
 ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
 ObjectOutputStream out = new ObjectOutputStream(byteOut);

 out.writeObject(map);
 out.close();
 UUID.nameUUIDFromBytes(byteOut.toByteArray());


然而,我想问一下这是否是最佳方式,如果不是,我应该尝试什么?

3
是的,UUID似乎满足您的需求。但是,如果您不将该密钥存储在其他数据结构中,生成UUID作为密钥的意义何在?您能提供更多有关您问题的背景信息吗? - Tim Biegeleisen
1
在地图中,每个元素是否应该具有唯一的ID,还是整个地图应该具有唯一的ID? - XtremeBaumer
2
您目前的示例可以工作,但我认为仅当地图完全相同时才有效。 具有相同内容但顺序不同的地图可能会导致不同的UUID,因为它们的toByteArray返回不同的值。 - Daniel Tung
@XtremeBaumer 只有地图本身。 - Luminous
@DanielTung 谢谢,你说得对,我完全忽略了它。这肯定不是应该的方式,但我不明白如何避免这种情况。 - Luminous
显示剩余5条评论
1个回答

2
为了达到这个目的,您可以使用任何适合您需求(在碰撞,性能方面)的哈希函数,例如SHA-1:

使用SHA-1哈希函数即可实现此功能:

public class MainClas {

    public static void main(String[] args) throws NoSuchAlgorithmException {
        Map<String, Integer> map = new HashMap<>();
        map.put("1", 1);
        map.put("2", 2);
        map.put("3", 3);

        String mapString = map.entrySet().toString();
        System.out.println(mapString);

        MessageDigest digest = MessageDigest.getInstance("SHA-1");
        byte[] hashBytes = digest.digest(mapString.getBytes());

        String hashString =  bytesToHex(hashBytes);

        System.out.println(hashString);
    }

    private static String bytesToHex(byte[] hashInBytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : hashInBytes) sb.append(String.format("%02x", b));
        return sb.toString();
    }
}

输出:

[1=1, 2=2, 3=3]
1a1677fe956c66c776a100b32b0a2b20fdabb5f3

附注:您可以通过使用来自不同算法(2或3个)产生的哈希的组合哈希来最小化碰撞。


那么,您建议的基本上是sha1吗?那我可以使用UUIDv5,因为它使用SHA-1。我看过几个实现,但默认包不包括它。您认为它比我目前使用的UUIDv3更好吗?就我所知,UUID具有非常小的碰撞机会,因此我不确定手动生成它是否合理。 - Luminous
1
@Luminous 我建议使用任何SHA-*,因为它是加密的。在哈希方面,它比md5更稳定。SHA-1产生20个字节的哈希值。但UUID只产生16个字节,并从16个字节中删除2个字节以设置版本和变体。结果,您在UUID VS 20字节SHA-1中仅具有14字节哈希值,这不好,基本上可能会产生更多的碰撞。为了最小化可能的碰撞,我建议根本不使用UUID,并使用由2或3种不同算法生成的复合键,例如key = sha1(bytes)+ sha256(bytes)或key = sha1(bytes)+ sha256(bytes)+ md5(bytes)。 - Matthew I.
那我应该忘记UUID5,因为它会将结果截短,实际上使用SHA-256或类似的方法。人们总是必须在他们的系统中实现自己的ID生成方法吗?我希望有一种明确的“好方法”,但似乎没有。感谢您如此清晰的解释! - Luminous
@Luminous 取决于任务和各种输入。但提前考虑并深入了解是很好的。欢迎您 :) - Matthew I.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接