【问题标题】:HashTable: in case of collisionHashTable:在发生碰撞的情况下
【发布时间】:2014-09-19 13:49:04
【问题描述】:
   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());

上面的代码 sn-p 正在打印 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

基本上都是碰撞列表。

【问题讨论】:

  • 您可以将列表存储为值。
  • 请注意,如今HashMap 通常比Hashtable 更受欢迎。

标签: java collections hashtable


【解决方案1】:

您当前使用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]

【讨论】:

  • 但如果我没记错的话,它应该作为列表存储在存储桶中。一切都应该自动运行。任何人都可以用示例解释我如何存储这些值并将每个存储桶作为列表获取。请(Java 新手)
  • @VrijendraKumarSingh 只需检查次要更新。我不小心把ht.put 放在if 语句之外,这是不必要的。
【解决方案2】:

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

您使用数字 i%10 (0,1,...,9) 作为键。因此,您只有 10 个不同的键。 例如:在您的 for 循环中,您为 key=5 (i=5, i=15, i=95) 放置 10 个值,每个 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;

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-17
    • 2022-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多