哈希表中的同一个键是否可以有多个值?如果没有,你能推荐任何可以使用的类或接口吗?
13 回答
不,这就是哈希表的想法。
但是,如果列表不存在,您可以使用 aMap<YourKeyObject, List<YourValueObject>>
和一些实用方法创建列表,或者使用类似Multimap
来自Google Collections的方法。
例子:
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
,使用 a可能会给您带来问题。如果您的地图仅在一个线程上使用,那将没有什么区别(并且您应该一直使用而不是无论如何)。HashMap
Hashtable
哈希表的值是对象,因此您可以存储列表
在哈希表中,人们将使用键/值对来存储信息。
在 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"
and的键/值对"World"
不在Hashtable
- 只有第二个"Hello"
和“ Mom
”条目在Hashtable
. 这表明不能有多个值与Hashtable
.
这里真正需要的是一个multimap,它允许将多个值关联到一个键。
多地图的一种实现Multimap
来自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
,但行为完全不同——aMultimap
允许将多个值关联到单个键。执行上述代码的结果如下:
Answer=42
Hello=Mom
Hello=World
可以看出,对于"Hello"
键,它的值"Mom"
和"World"
与之关联的值。与 不同Hashtable
,它不会丢弃其中一个值并将其替换为另一个值。Multimap
能够为每个键保留多个值。
与其给出另一个 multipmap 答案,不如问你为什么要这样做?
多个值是否相关?如果是,那么最好创建一个数据结构来保存它们。如果不是,那么使用单独的地图可能更合适。
您是否将它们放在一起以便可以根据密钥对其进行迭代?您可能想要寻找另一种索引数据结构,例如 SkipList。
只需制作自己的:
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);
}
}
正如其他人指出的那样,没有。相反,请考虑使用Multimap
可以为同一个键映射多个值的 a。
Google Collections ( update : Guava )库包含一个实现,可能是您最好的选择。
编辑:当然,您可以按照Eric 的建议进行操作,并将 Collection 作为值存储在您的 Hashtable(或 Map,更一般地说)中,但这意味着您自己编写不必要的样板代码。当使用像 Google Collections 这样的库时,它会为你处理低级的“管道”。查看这个很好的示例,了解如何通过使用 Multimap 而不是 vanilla Java Collections 类来简化您的代码。
没有一个答案表明我首先会做什么。
我在 OO 能力方面取得的最大飞跃是当我决定总是开设另一个课程时,它似乎甚至可能有点用——这是我从遵循这种模式中学到的东西之一。
几乎一直,我发现我试图放入哈希表的对象之间存在关系。通常情况下,有一个类的空间——甚至是一两个方法。
事实上,我经常发现我什至不需要 HashMap 类型的结构——一个简单的 HashSet 就可以了。
您作为主键存储的项目可以成为新对象的标识——因此您可以创建仅引用该对象的 equals 和 hash 方法(eclipse 可以轻松地为您创建 equals 和 hash 方法)。这样,新对象将与原始对象完全一样保存、排序和检索,然后使用属性来存储其余项目。
大多数时候,当我这样做时,我发现也有一些方法可以去那里,在我知道之前,我有一个应该一直在那里但我从未认出的成熟对象,还有一堆垃圾我的代码中的因素。
为了使它更像是一个“婴儿步骤”,我经常创建包含在我的原始类中的新类——有时我什至将这个类包含在一个方法中,如果这样定义它是有意义的——然后我移动它随着它变得更加清晰,它应该是一流的。
简单的。而不是
Hashtable<Key, Value>
,使用Hashtable<Key, Vector<Value>>
.
有关多地图和类似的此类收藏,请参阅Google 收藏库。内置集合对此没有直接支持。
您正在寻找的是Multimap。google collections api提供了一个很好的实现,还有很多值得学习使用的东西。强烈推荐!
您需要使用称为MultiMap的东西。这不是严格意义上的地图,但它是一个不同的 API。它与 Map<K, List<V>> 大致相同,但您不会有像 entrySet() 或 values() 这样的方法。
以下代码没有 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());
}
除了 Google Collections 之外,还有一个用于 MultiMap的apache Commons Collection对象