HashMap的大小错误

时间:2018-11-22 22:49:25

标签: java hashmap set

我试图将某些键作为字节[]从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?
    }

}

3 个答案:

答案 0 :(得分:3)

哈希冲突的概率为(seen here):

graph

在给定n输入的情况下,一组大小为k的平均碰撞次数为:

N(n,k)~=k(k-1)/(2n)

鉴于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)

如果您的SetHashMap的大小不同,则可能是按键冲突。 看来您的函数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());

或仅通过使用调试器