我试图将某些键作为字节[]从HashSet导出到HashMap,并使用HashMap来存储数据对。但是,由于某种原因,我遇到了一个问题,即集合的大小大于HashMap的大小。我想知道是什么原因造成的,因为HashMap在foreach中,它从0迭代到HashSet的大小,即2 ^ 20。因此,我也希望HashMap的大小也为2 ^ 20。
因此,我要存储在HashMap中的是两个字节数组。我目前正在研究2DES的中间相遇攻击。我的加密已正确实施。另外,我的DES密钥生成器也已正确实现,因此我能够生成2 ^ 20个密钥(只有20位有效)。但是,当我尝试将键放入HashMap时,其大小与HashSet不同,这没有任何意义。
for (int i = 0; i < Math.pow(2, 20); i++) {
possibleKeySet.add(generateDesKey());
}
for (byte[] key : possibleKeySet) {
intermediateCipher.put((encrypt(key, plainText)).toString(), key);
}
输出:
设置大小:1048576
地图尺寸:1048295
PS:intermediateCipher是我的HashMap。
更新: 我已经尝试实现哈希码和等于,但是我不确定如何实现哈希码。
class ByteArray {
private byte[] key;
ByteArray(byte[] key) {
this.key = key;
}
byte[] getKey() {
return key;
}
public boolean equals(Object obj) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(obj);
oos.writeObject(obj);
oos.flush();
byte [] data = bos.toByteArray();
return key.equals(data);
}
public int hashCode() {
// what should I write here?
}
}
答案 0 :(得分:3)
哈希冲突的概率为(seen here):
在给定n
输入的情况下,一组大小为k
的平均碰撞次数为:
鉴于n
的{{1}}和2^32
的{{1}},平均碰撞为
k
您看到的冲突数量为2^20
。鉴于此信息,我假设(2^20) * (2^20 - 1) / (2 * 2^32)
~= 2^40/2^33
~= 2^7
~= 128
返回的值的实际熵大约为31位(而不是32位)。
要获得所需数量的键,您可能想要一直生成值,直到达到所需大小。这可能会使该方法花费很长时间才能完成:
1048576 - 1048295 = 281
答案 1 :(得分:1)
如果您的Set
和HashMap
的大小不同,则可能是按键冲突。
看来您的函数encrypt(key, plainText)
返回重复项。
尝试:
for (byte[] key : possibleKeySet) {
Object oldValue = intermediateCipher.put((encrypt(key, plainText)).toString(), key);
if(oldValue != null) {
System.out.println("Duplicated!");
}
}
它可能会产生一些错误。
还请注意,generateDesKey()
也可以产生相同的值,即使它们存储在Set
中也是如此,因为Java中的两个数组只有在它们是同一对象的情况下才相等。
您能做什么?创建一个自定义对象:
class ByteArray {
private byte[] key;
ByteArray(byte[] key) {
this.key = key;
}
byte[] getKey() {
return key;
}
public boolean equals(Object obj) {
//implement your equals logic using array members equality
}
public int hashCode() {
//implement your hashCode logic using array members equality
}
}
答案 2 :(得分:0)
该集合本身的实现方式是,其中的每个项目都必须是唯一的-不允许重复。这意味着当您要在结果集中设置两个相等的对象时,将只有一个。
您的generateDesKey()
方法可能返回的不是所有2^20
值的唯一值,并且在结果集中,项数小于2^20
基本上,您可以先检查possibleKeySet
的大小,然后再将值复制到HashMap
,例如
System.out.println(possibleKeySet.size());
或仅通过使用调试器