哈希表中是否可以为同一个键设置多个值?如果没有,你能建议任何可以使用的类或接口吗?
答案 0 :(得分:21)
没有。这就是哈希表的想法。
但是,您可以使用Map<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
可能会导致问题。如果您的地图仅在一个主题上使用,则不会产生任何影响(您应该使用HashMap
而不是Hashtable
。
答案 1 :(得分:11)
哈希表的值是Object,因此您可以存储List
答案 2 :(得分:7)
我会问你为什么要这样做,而不是给出另一个多重图答案?
多个值是否相关?如果是,那么创建一个数据结构来保存它们可能会更好。如果不是,那么使用单独的地图可能更合适。
您是否将它们保持在一起,以便您可以根据密钥进行迭代?您可能希望寻找替代索引数据结构,如SkipList。
答案 3 :(得分:7)
在哈希表中,可以使用键/值对来存储信息。
在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
中的条目1}}:
Answer=42
Hello=Mom
"Hello"
和"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
的示例,但行为完全不同 - Multimap
允许将多个值关联到单个键。执行上述代码的结果如下:
Answer=42
Hello=Mom
Hello=World
可以看出,对于"Hello"
密钥,"Mom"
和"World"
的值与之关联。与Hashtable
不同,它不会丢弃其中一个值并将其替换为另一个值。 Multimap
能够保留每个密钥的多个值。
答案 4 :(得分:5)
正如其他人指出的那样,没有。相反,请考虑使用Multimap
,它可以为同一个键映射多个值。
Google Collections ( update :Guava)库包含一个实现,可能是您最好的选择。
编辑:当然您可以Eric suggests执行,并将集合作为值存储在Hashtable(或更常见的地图)中,但这意味着您自己编写不必要的样板代码。使用Google Collections这样的库时,会为您处理低级别的“管道”。通过使用Multimap而不是vanilla Java Collections类,查看nice example如何简化代码。
答案 5 :(得分:4)
没有一个答案表明我先做的事情。
我在OO能力方面取得的最大跳跃是当我决定在看起来它甚至可能稍微有用的时候总是进行另一个课程 - 这是我从遵循该模式学到的事情之一。
几乎所有时间,我发现我试图放入哈希表的对象之间存在关系。通常,有一个班级的空间 - 甚至是一两种方法。
事实上,我经常发现我甚至不想要一个HashMap类型结构 - 一个简单的HashSet就可以了。
您作为主键存储的项目可以成为新对象的标识 - 因此您可以创建仅引用该对象的equals和hash方法(eclipse可以轻松地为您创建equals和hash方法)。这样新的对象将保存,排序&amp;完全按照原始版本检索,然后使用属性存储其余项目。
大多数时候,当我这样做时,我发现有一些方法可以去那里,在我知道它之前我有一个完整的对象应该一直存在但我从未认识到,并且我的代码中有很多垃圾因素。
为了使它更像是一个“Baby step”,我经常创建我原始类中包含的新类 - 有时我甚至在方法中包含类,如果有意义的那样 - 那么我移动它,因为它变得更加清晰,它应该是一流的类。
答案 6 :(得分:4)
自己制作:
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);
}
}
答案 7 :(得分:2)
有关多图和类似此类集合的信息,请参阅Google Collections Library。内置集合没有直接支持。
答案 8 :(得分:2)
您要找的是Multimap。 google collections api提供了很好的实现,以及其他值得学习使用的内容。强烈推荐!
答案 9 :(得分:1)
您需要使用名为MultiMap的内容。这不是严格意义上的Map,但它是一个不同的API。它与Map&lt; K,List&lt; V&gt;&gt;大致相同,但您不会使用entrySet()或values()等方法。
答案 10 :(得分:1)
简单。代替
Hashtable<Key, Value>
,使用Hashtable<Key, Vector<Value>>
。
答案 11 :(得分:0)
除了Google Collections之外,还有一个apache Commons Collection对象 for MultiMap
答案 12 :(得分:0)
以下代码没有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());
}