HashTable:遇到碰撞

时间:2014-09-19 13:49:04

标签: java collections hashtable

   Hashtable ht = new Hashtable();
    for (int i = 0; i < 100; i++) {
        ht.put(i%10, i);
    }

    Enumeration< Integer> eles = ht.elements();
    while(eles.hasMoreElements())
        System.out.println(eles.nextElement());

上面的代码片段是打印99,98,....... 90

但我想要打印所有100个元素。 如何获得像...这样的数字列表 99,89,79,69,... 19.9 98,88,78,68 .... 18,8 97,87,77,67 .... 17,7 .. .. 91,81,71,61 .... 11,1

基本上都是碰撞清单。

2 个答案:

答案 0 :(得分:6)

您当前正在使用i % 10作为哈希映射键,它只有十个值(0-9)。因此,只有最后十个值存储在地图中,所有其他值都被覆盖。

如果您需要在每个存储桶中存储多个项目,请使用列表类型作为您的值。例如:

Hashtable<Integer, List<Integer>> ht = new Hashtable<>();
for (int i = 0; i < 100; i++) {
  int key = i % 10;
  List<Integer> list = ht.get(key);
  if (list == null) {
    list = new ArrayList<>();
    ht.put(key, list);
  }
  list.add(i);      
}

Enumeration<List<Integer>> eles = ht.elements();
while (eles.hasMoreElements()) {
  System.out.println(Arrays.toString(eles.nextElement().toArray()));
}

输出:

[9, 19, 29, 39, 49, 59, 69, 79, 89, 99]
[8, 18, 28, 38, 48, 58, 68, 78, 88, 98]
[7, 17, 27, 37, 47, 57, 67, 77, 87, 97]
[6, 16, 26, 36, 46, 56, 66, 76, 86, 96]
[5, 15, 25, 35, 45, 55, 65, 75, 85, 95]
[4, 14, 24, 34, 44, 54, 64, 74, 84, 94]
[3, 13, 23, 33, 43, 53, 63, 73, 83, 93]
[2, 12, 22, 32, 42, 52, 62, 72, 82, 92]
[1, 11, 21, 31, 41, 51, 61, 71, 81, 91]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

答案 1 :(得分:0)

您在示例中观察到的是不是碰撞效果。这是正常的元素替换。 在100次迭代之后,Hashtable中只有10个元素。

您使用数字i%10(0,1,...,9)作为键。所以,你只有10个不同的键。 例如:在你的for循环中,你为key = 5放置10个值(i = 5,i = 15,i = 95),每个put(5,val)替换与key = 5相关的旧值。

碰撞清单是不同的概念。

对于每个密钥哈希表计算一些哈希值并使用此哈希在其内部桶表中选择索引。接下来在该索引下放置{key,value}。 碰撞是指2个不同的密钥计算了相同的桶索引的情况。

例如:

table index   |  map.entry
0             |  {0, "A"}
1             |  {3, "B"}
2             |  {2, "A"} -> {4, "C"}
3             |  {1, "D"} -> {5, "A} -> {6, "F} 

在此示例中,您有具有4元素内部表的哈希表。 此哈希表包含7个元素(7个不同的键)但是:

键2和3放在同一个桶中(它们具有根据哈希值计算的相同索引) 键1,5,6被放置在同一个桶中。

所以我们可以说,key = 2和key = 3之间以及1,5,6之间存在冲突。 换句话说,键2和3在同一个碰撞列表上。键1,5,6也是如此。

不能从Hashtable获取此类冲突列表,因为它是标记为私有的Hashtable内部实现:

/**
 * Hashtable bucket collision list entry
 */
private static class Entry<K,V> implements Map.Entry<K,V> {

int hash;
final K key;
V value;
Entry<K,V> next;

protected Entry(int hash, K key, V value, Entry<K,V> next) {
    this.hash = hash;
    this.key =  key;
    this.value = value;
    this.next = next;
}

...

public V setValue(V value) {
    if (value == null)
        throw new NullPointerException();

    V oldValue = this.value;
    this.value = value;
    return oldValue;
}

...

public int hashCode() {
    return hash ^ value.hashCode();
}

...

}

Hashtable将其内部存储桶表定义为:

/**
 * The hash table data.
 */
private transient Entry<K,V>[] table;

希望这有助于找出哈希表行为。