Java中的多值哈希表

Posted

技术标签:

【中文标题】Java中的多值哈希表【英文标题】:Multi-valued hashtable in Java 【发布时间】:2010-11-06 04:42:36 【问题描述】:

哈希表中的同一个键可以有多个值吗?如果没有,你能推荐任何可以使用的类或接口吗?

【问题讨论】:

Awseome 6 个人基本上都在复制和粘贴相同的答案。 叹息 太棒了,6个人独立得出了相同的答案。耶! 我敢打赌,如果有人愿意看而不是仅仅敲打一个明显的帖子,那是一个愚蠢的问题。 我确实看过,但我没有看到任何明显的重复。还有人想试试吗? 我也搜过;没找到。我会说如果存在重复,它会以某种非常晦涩的方式命名/标记 【参考方案1】:

没有。这就是哈希表的想法。

但是,如果列表不存在,您可以使用Map<YourKeyObject, List<YourValueObject>> 和一些用于创建列表的实用方法自行创建列表,或者使用Google Collections 中的Multimap 之类的方法。

示例:

String key = "hello";
Multimap<String, Integer> myMap = HashMultimap.create();
myMap.put(key, 1);
myMap.put(key, 5000);
System.out.println(myMap.get(key)); // prints either "[1, 5000]" or "[5000, 1]"
myMap = ArrayListMultimap.create();
myMap.put(key, 1);
myMap.put(key, 5000);
System.out.println(myMap.get(key)); // always prints "[1, 5000]"

请注意,Multimap 不是自制解决方案的精确等价物; Hashtable 同步它的所有方法,而Multimap 不做这样的保证。这意味着使用Multimap 可能会给您带来问题如果您在多个线程上使用它。如果您的地图仅在一个线程上使用,那将没有什么区别(而且您应该一直使用 HashMap 而不是 Hashtable)。

【讨论】:

有趣的是,Multimap 基本上只是在幕后做 Map> 是的,它基本上只是抽象掉了非常重要的细节。【参考方案2】:

哈希表的值是对象,所以你可以存储一个列表

【讨论】:

是的,您可以存储一个列表,但您不能只向其中添加项目,您必须获取对列表的引用,然后将其添加到列表中。【参考方案3】:

在哈希表中,可以使用键/值对来存储信息。

在 Java 中,Hashtable 类接受单个键的单个值。以下是尝试将多个值关联到单个键的示例:

Hashtable<String, String> ht = new Hashtable<String, String>();

ht.put("Answer", "42");
ht.put("Hello", "World");    // First value association for "Hello" key.
ht.put("Hello", "Mom");      // Second value association for "Hello" key.

for (Map.Entry<String, String> e : ht.entrySet()) 
  System.out.println(e);

为了尝试将多个值("World""Mom")包含到单个键("Hello")中,我们最终会得到以下结果以打印 Hashtable 中的条目:

Answer=42
Hello=Mom

"Hello""World" 的键/值对不在 Hashtable 中 -- 只有第二个 "Hello" 和“Mom”条目在 Hashtable 中。这表明不能有多个值与Hashtable 中的单个键相关联。


这里真正需要的是multimap,它允许将多个值关联到一个键。

多重映射的一个实现是Multimap from Google Collections:

Multimap<String, String> mm = HashMultimap.create();

mm.put("Answer", "42");
mm.put("Hello", "World");
mm.put("Hello", "Mom");

for (Map.Entry<String, String> e : mm.entries()) 
  System.out.println(e);

这类似于上面使用Hashtable 的示例,但行为完全不同——Multimap 允许将多个值关联到单个键。上述代码执行结果如下:

Answer=42
Hello=Mom
Hello=World

可以看出,对于"Hello"键,"Mom""World"的值与之关联。与Hashtable 不同,它不会丢弃其中一个值并将其替换为另一个值。 Multimap 能够为每个键保留多个值。

【讨论】:

+1,不是为了独创性,而是为了示例的清晰和彻底:)【参考方案4】:

与其给出另一个 multipmap 答案,我会问你为什么要这样做?

多个值是否相关?如果是,那么最好创建一个数据结构来保存它们。如果不是,那么使用单独的地图可能更合适。

您是否将它们放在一起以便可以根据键对其进行迭代?您可能想寻找另一种索引数据结构,例如 SkipList。

【讨论】:

+1 用于查看全局。我总是忘记这样做。 嗯,你会推荐什么 SkipList 实现?显然 JDK 没有提供(如果我错了,请纠正我)。【参考方案5】:

自己做吧:

Map<Object, List<Object>> multiMap = new HashMap<Object, List<Object>>();

添加:

  public void add(String key, Object o) 
    List<Object> list;
    if (multiMap.containsKey(key)) 
      list = multiMap.get(key);
      list.add(o);
     else 
      list = new ArrayList<Object>();
      list.add(o);
      multiMap.put(key, list);
    
  

【讨论】:

没有外部库,这是要走的路。但这正是我在回答中提到的样板;使用 Google Collections,添加将是 one 行,简单地说:multiMap.put(key, o)【参考方案6】:

正如其他人指出的那样,不。相反,请考虑使用Multimap,它可以为同一个键映射多个值。

Google Collections更新:Guava)库包含一个实现,可能是您最好的选择。

编辑:当然你可以像Eric suggests 那样做,并将一个Collection 作为一个值存储在你的Hashtable(或者更一般的Map)中,但这意味着你要自己编写不必要的样板代码。当使用像 Google Collections 这样的库时,它会为你处理低级的“管道”。查看nice example,了解如何使用 Multimap 而不是普通的 Java Collections 类来简化代码。

【讨论】:

【参考方案7】:

没有一个答案表明我首先会做什么。

我的 OO 能力最大的飞跃是当我决定总是创建另一个类时,它看起来甚至可能有点用处——这是我从遵循这种模式中学到的东西之一。

几乎一直,我发现我试图放入哈希表的对象之间存在关系。通常情况下,有一个类的空间——甚至是一两个方法。

事实上,我经常发现我什至不需要 HashMap 类型的结构——一个简单的 HashSet 就可以了。

您作为主键存储的项目可以成为新对象的标识——因此您可以创建仅引用该对象的 equals 和 hash 方法(eclipse 可以轻松地为您创建 equals 和 hash 方法)。这样,新对象将与原始对象完全一样保存、排序和检索,然后使用属性来存储其余项目。

大多数时候,当我这样做时,我发现也有一些方法可以使用,在我知道之前,我有一个完整的对象,它应该一直在那里,但我从来没有认出,还有一个我的代码中有一堆垃圾因素。

为了使它更像是一个“小步骤”,我经常创建包含在我原来的类中的新类——有时我什至将类包含在一个方法中,如果以这种方式限定它是有意义的——然后我移动它,因为它变得更加清楚它应该是一流的。

【讨论】:

【参考方案8】:

查看Google Collections Library 了解多图和类似的此类集合。内置集合对此没有直接支持。

【讨论】:

【参考方案9】:

您要查找的是Multimap。 google collections api 提供了一个很好的实现,还有很多值得学习使用的东西。强烈推荐!

【讨论】:

在阅读了其他人的答案后,我不得不得出结论,我对 google collections api 的倡导并不是很原创。 (这是一部好作品,不是吗?) 我链接到 commons-collections 只是为了与众不同 :-P(实际上这是第一次搜索命中,我感到很懒惰)。【参考方案10】:

简单。代替 Hashtable&lt;Key, Value&gt;,使用Hashtable&lt;Key, Vector&lt;Value&gt;&gt;

【讨论】:

只是一个小小的说明:HashMap 默认是不同步的,为什么要在其中使用 Vector 而不是 List 实现呢? 嗯,最初的问题是关于 HashTables,而不是 HashMaps。 是的,这就是为什么这个答案使用 HashMap 和 Vector(而不是 Hashtable 和 Vector 或 HashMap 和 ArrayList 等)很好奇的原因。IMO,在教学上最好使用 Map 和 List。 :)【参考方案11】:

您需要使用称为MultiMap 的东西。这不是严格意义上的地图,但它是一个不同的 API。它与 Map> 大致相同,但不会有 entrySet() 或 values() 之类的方法。

【讨论】:

能否请您至少发布一个小的示例代码以供使用? 我更喜欢 Google Collections,因为 Apache Commons 不支持泛型。 有关 Google Collections 与 Apache Commons Collections 的更多信息,请参阅javalobby.org/articles/google-collections(搜索“Apache Commons”)【参考方案12】:

除了 Google Collections 之外,还有一个 apache Commons Collection 对象 多图

【讨论】:

【参考方案13】:

以下代码没有 Google 的 Guava 库。它用于双值作为键和排序顺序

Map<Double,List<Object>> multiMap = new TreeMap<Double,List<Object>>();

for( int i= 0;i<15;i++)

    List<Object> myClassList = multiMap.get((double)i);
    if(myClassList == null)
    
        myClassList = new ArrayList<Object>();
        multiMap.put((double) i,myClassList);
    
    myClassList.add("Value "+ i);


List<Object> myClassList = multiMap.get((double)0);
if(myClassList == null)

    myClassList = new ArrayList<Object>();
    multiMap.put( (double) 0,myClassList);

myClassList.add("Value Duplicate");
for (Map.Entry entry : multiMap.entrySet()) 

  System.out.println("Key = " + entry.getKey() + ", Value = " +entry.getValue());

【讨论】:

以上是关于Java中的多值哈希表的主要内容,如果未能解决你的问题,请参考以下文章

Java集合哈希表及哈希函数的实现方式

iOS中的哈希表

有关java中的hashCode问题

Java的HashMap

Java集合框架中的Hashtable、HashMap、HashSet、哈希表概念

Java集合框架中的Hashtable,HashMap,HashSet,哈希表概念