简体   繁体   English

Java中的多值哈希表

[英]Multi-valued hashtable in Java

Is it possible to have multiple values for the same key in a hash table? 是否可以在哈希表中为同一个键设置多个值? If not, can you suggest any such class or interface which could be used? 如果没有,你能建议任何可以使用的类或接口吗?

No. That's kind of the idea of hash tables. 不,这就是哈希表的想法。

However, you could either roll your own with a Map<YourKeyObject, List<YourValueObject>> and some utility methods for creating the list if it's not present, or use something like the Multimap from Google Collections . 但是,您可以使用Map<YourKeyObject, List<YourValueObject>>以及一些用于创建列表的实用程序方法(如果它不存在)来滚动您自己的方法,或者使用类似Google Collections中Multimap

Example: 例:

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]"

Note that Multimap is not an exact equivalent of the home-baked solution; 请注意, Multimap并不完全等同于自制解决方案; Hashtable synchronizes all its methods, while Multimap makes no such guarantee. Hashtable同步其所有方法,而Multimap没有这样的保证。 This means that using a Multimap may cause you problems if you are using it on multiple threads . 这意味着如果在多个线程上使用Multimap ,使用Multimap可能会导致问题。 If your map is used only on one thread, it will make no difference (and you should have been using HashMap instead of Hashtable anyway). 如果你的地图只在一个线程上使用,它就没有区别(你应该使用HashMap而不是Hashtable )。

哈希表的值是Object,因此您可以存储List

Rather than give yet another multipmap answer, I'll ask why you want to do this? 而不是给出另一个多重映射答案,我会问你为什么要这样做?

Are the multiple values related? 多个值是否相关? If yes, then it's probably better that you create a data structure to hold them. 如果是,那么创建一个数据结构来保存它们可能会更好。 If no, then perhaps it's more appropriate to use separate maps. 如果不是,那么使用单独的地图可能更合适。

Are you keeping them together so that you can iterate them based on the key? 您是否将它们保持在一起,以便您可以根据密钥对它们进行迭代? You might want to look for an alternative indexing data structure, like a SkipList. 您可能希望寻找替代索引数据结构,如SkipList。

In a hashtable, one would use a key/value pair to store information. 在哈希表中,可以使用键/值对来存储信息。

In Java, the Hashtable class accepts a single value for a single key. 在Java中, Hashtable类接受单个键的单个值。 The following is an example of an attempt to associate multiple values to a single key: 以下是尝试将多个值关联到单个键的示例:

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);
}

In an attempt to include multiple values ( "World" , "Mom" ) to a single key ( "Hello" ), we end up with the following result for printing the entries in the Hashtable : 为了将多个值( "World""Mom" )包含到单个键( "Hello" )中,我们最终得到以下结果来打印Hashtable的条目:

Answer=42
Hello=Mom

The key/value pair of "Hello" and "World" is not in the Hashtable -- only the second "Hello" and " Mom " entry is in the Hashtable . "Hello""World"的键/值对不在Hashtable - 只有第二个"Hello"和“ Mom ”条目在Hashtable This shows that one cannot have multiple values associate with a single key in a Hashtable . 这表明不能将多个值与Hashtable的单个键相关联。


What is really needed here is a multimap , which allows an association of multiple values to a single key. 这里真正需要的是一个multimap ,它允许将多个值关联到一个键。

One implementation of the multimap is Multimap from Google Collections : 多图的一个实现是来自Google Collections的 Multimap

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);
}

This is similar to the example above which used Hashtable , but the behavior is quite different -- a Multimap allows the association of multiple values to a single key. 这类似于上面使用Hashtable的示例,但行为完全不同 - Multimap允许将多个值关联到单个键。 The result of executing the above code is as follows: 执行上述代码的结果如下:

Answer=42
Hello=Mom
Hello=World

As can be seen, for the "Hello" key, the values of "Mom" and "World" associated with it. 可以看出,对于"Hello"键, "Mom""World"与之关联。 Unlike Hashtable , it does not discard one of the values and replace it with another. Hashtable不同,它不会丢弃其中一个值并将其替换为另一个值。 The Multimap is able to hold on to multiple values for each key. Multimap能够为每个键保留多个值。

As others pointed out, no. 正如其他人指出的那样,没有。 Instead, consider using a Multimap which can map many values for the same key. 相反,请考虑使用Multimap ,它可以为同一个键映射许多值。

The Google Collections ( update : Guava ) library contains one implementation, and is probably your best bet. Google Collections更新Guava )库包含一个实现,可能是您最好的选择。

Edit : of course you can do as Eric suggests , and store a Collection as a value in your Hashtable (or Map, more generally), but that means writing unnecessary boilerplate code yourself. 编辑 :当然你可以像Eric建议的那样做,并将Collection作为值存储在你的Hashtable(或更普遍的Map)中,但这意味着自己编写不必要的样板代码。 When using a library like Google Collections, it would take care of the low-level "plumbing" for you. 使用Google Collections这样的库时,会为您处理低级别的“管道”。 Check out this nice example of how your code would be simplified by using Multimap instead of vanilla Java Collections classes. 查看使用Multimap而不是vanilla Java Collections类简化代码的简单示例

None of the answers indicated what I would do first off. 没有一个答案表明我先做什么。

The biggest jump I ever made in my OO abilities was when I decided to ALWAYS make another class when it seemed like it might be even slightly useful--and this is one of the things I've learned from following that pattern. 我在OO能力方面取得的最大跳跃是当我决定总是创建另一个类时,它似乎甚至可能有点用处 - 这是我从遵循该模式学到的东西之一。

Nearly all the time, I find there is a relationship between the objects I'm trying to place into a hash table. 几乎所有时间,我发现我试图放入哈希表的对象之间存在关系。 More often than not, there is room for a class--even a method or two. 通常情况下,课堂上有空间 - 甚至是一两种方法。

In fact, I often find that I don't even want a HashMap type structure--a simple HashSet does fine. 事实上,我经常发现我甚至不想要一个HashMap类型结构 - 一个简单的HashSet就可以了。

The item you are storing as the primary key can become the identity of a new object--so you might create equals and hash methods that reference only that one object (eclipse can make your equals and hash methods for you easily). 您作为主键存储的项目可以成为新对象的标识 - 因此您可以创建仅引用该对象的equals和hash方法(eclipse可以轻松地为您创建equals和hash方法)。 that way the new object will save, sort & retrieve exactly as your original one did, then use properties to store the rest of the items. 这样,新对象将像原始对象一样保存,排序和检索,然后使用属性来存储其余项目。

Most of the time when I do that, I find there are a few methods that go there as well and before I know it I have a full-fledged object that should have been there all along but I never recognized, and a bunch of garbage factors out of my code. 大多数时候,当我这样做时,我发现有一些方法可以去那里,在我知道它之前我有一个完整的对象应该一直存在但我从来没有认识到,和一堆垃圾我的代码中的因素。

In order to make it more of a "Baby step", I often create the new class contained in my original class--sometimes I even contain the class within a method if it makes sense to scope it that way--then I move it around as it becomes more clear that it should be a first-class class. 为了使它更像是一个“宝贝步骤”,我经常创建我原始类中包含的新类 - 有时我甚至在方法中包含类,如果它以这种方式调整范围 - 然后我移动它因为它变得更加清晰,它应该是一流的课程。

Just make your own: 做你自己的:

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

To add: 加上:

  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);
    }
  }

See the Google Collections Library for multimaps and similar such collections. 有关多图和类似此类集合的信息,请参阅Google Collections Library The built-in collections don't have direct support for this. 内置集合没有直接支持。

What you're looking for is a Multimap . 您正在寻找的是Multimap The google collections api provides a nice implementation of this and much else that's worth learning to use. 谷歌收藏api提供了一个很好的实现,以及其他值得学习使用的东西。 Highly recommended! 强烈推荐!

You need to use something called a MultiMap . 您需要使用称为MultiMap的东西。 This is not strictly a Map however, it's a different API. 这不是严格意义上的Map,但它是一个不同的API。 It's roughly the same as a Map<K, List<V>>, but you wont have methods like entrySet() or values(). 它与Map <K,List <V >>大致相同,但您不会使用entrySet()或values()等方法。

Simple. 简单。 Instead of Hashtable<Key, Value> , use Hashtable<Key, Vector<Value>> . 而不是Hashtable<Key, Value> ,使用Hashtable<Key, Vector<Value>>

Following code without Google's Guava library. 以下代码没有谷歌的Guava库。 It is used for double value as key and sorted order 它用于双值作为键和排序顺序

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对象

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM