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哈希表的值是对象,所以你可以存储一个列表
【讨论】:
是的,您可以存储一个列表,但您不能只向其中添加项目,您必须获取对列表的引用,然后将其添加到列表中。【参考方案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<Key, Value>
,使用Hashtable<Key, Vector<Value>>
。
【讨论】:
只是一个小小的说明:HashMap 默认是不同步的,为什么要在其中使用 Vector 而不是 List 实现呢? 嗯,最初的问题是关于 HashTables,而不是 HashMaps。 是的,这就是为什么这个答案使用 HashMap 和 Vector(而不是 Hashtable 和 Vector 或 HashMap 和 ArrayList 等)很好奇的原因。IMO,在教学上最好使用 Map 和 List。 :)【参考方案11】:您需要使用称为MultiMap 的东西。这不是严格意义上的地图,但它是一个不同的 API。它与 Map
【讨论】:
能否请您至少发布一个小的示例代码以供使用? 我更喜欢 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中的多值哈希表的主要内容,如果未能解决你的问题,请参考以下文章