在Java中单独链接HashTables

时间:2014-06-22 08:13:34

标签: java hash hash-collision

基于以下代码段:

  Hashtable balance = new Hashtable();
  Enumeration names;
  String str;
  double bal;

  balance.put("Zara", new Double(3434.34)); //first entry for Zara
  balance.put("Mahnaz", new Double(123.22));
  balance.put("Zara", new Double(1378.00)); //second entry for Zara
  balance.put("Daisy", new Double(99.22));
  balance.put("Qadir", new Double(-19.08));

  System.out.println(balance.entrySet());

Output : [Qadir=-19.08, Mahnaz=123.22, Daisy=99.22, Zara=1378.0]
  1. 为什么链接不会发生在这里?当我以Zara作为键重新进入时,旧值被覆盖。我希望在 Zara" .hashcode()索引的链接列表末尾添加它。
  2. Java是否仅为碰撞处理使用单独的链接?
  3. 如果我不能使用链接(正如我上面尝试的那样),请提出一个常用方法。

2 个答案:

答案 0 :(得分:4)

  

Java是否仅为碰撞处理使用单独的链接?

是。您只能在Hashtable(或HashMap中为每个键创建一个条目,这是您应该使用的 - 以及泛型)。它是键/值映射,而不是键/多值映射。在哈希表的上下文中,术语" collision"通常用于两个不等键具有相同哈希码的情况。它们仍然需要被视为不同的密钥,因此实现必须应对这一点。那不是你所处的情况。

听起来你可能想要一张多地图,比如Guava中的一张。然后,您可以向multimap询问与特定密钥关联的所有值。

编辑:如果您想构建自己的多重地图,您可以使用以下内容:

// Warning: completely untested
public final class Multimap<K, V> {
    private final Map<K, List<V>> map = new HashMap<>();

    public void add(K key, V value) {
        List<V> list = map.get(key);
        if (list == null) {
            list = new ArrayList();
            map.put(key, list);
        }
        list.add(value);
    }

    public Iterable<V> getValues(K key) {
        List<V> list = map.get(key);
        return list == null ? Collections.<V>emptyList()
                            : Collections.unmodifiableList(list);
    }
}

答案 1 :(得分:3)

来自the documentation of Map的引用(Hashtable是其实现):

  

将键映射到值的对象。 地图不能包含重复的键;每个键最多可以映射一个值。

(强调我的)

documentation of put()也说:

  

如果地图以前包含该键的映射,则旧值将替换为指定值

因此,如果您想要与关键字相关联的多个值,请使用Map<String, List<Double>>而不是Map<String, Double>。 Guava还有一个Multimap,它可以满足您的需求而无需像Map<String, List<Double>>一样明确地处理列表。