如何在地图中使用具有多个值的键?

时间:2012-12-05 09:44:03

标签: java map

我有这样的地图

Map map=new HashMap();//HashMap key random order.
map.put("a",10);
map.put("a",20);
map.put("a",30);
map.put("b",10);

System.out.println("There are "+map.size()+" elements in the map.");
System.out.println("Content of Map are...");
Set s=map.entrySet();
Iterator itr=s.iterator();
while(itr.hasNext())
{
    Map.Entry m=(Map.Entry)itr.next();
    System.out.println(m.getKey()+"\t"+m.getValue()+"\t"+ m.hashCode());
}

上述程序的输出是

There are 2 elements in the map.
Content of Map are...
b   10  104
a   30  127

现在我想要那个键应该有多个值,比如

a 10
a 20
a 30

这样我就可以得到一个关联的所有值。请告诉我如何实现同样的目标。通过嵌套集合,我希望键'a'具有所有三个值。

6 个答案:

答案 0 :(得分:13)

你签出了Guava Multimaps吗?

  

类似于Map的集合,但可以关联多个值   用一把钥匙。如果您使用相同的键调用put(K,V)两次,但是   不同的值,multimap包含从键到两者的映射   值。

如果你真的想使用标准集合(如下所示),你必须为每个键存储一个集合,例如。

map = new HashMap<String, Collection<Integer>>();

请注意,首次输入新密钥时,您必须在添加第一个值之前创建新集合(ListSet等)。

答案 1 :(得分:4)

要使用Java标准库实现您想要的,我会使用这样的地图:

Map<String, Collection<Integer>> multiValueMap = new HashMap<String, Collection<Integer>>();

然后你可以添加值:

multiValueMap.put("a", new ArrayList<Integer>());
multiValueMap.get("a").add(new Integer(10));
multiValueMap.get("a").add(new Integer(20));
multiValueMap.get("a").add(new Integer(30));

如果这对您造成不舒服,请考虑将此行为包装在专用类中,或使用第三方解决方案,正如其他人在此处所建议的那样(Guava Multimap)。

答案 2 :(得分:2)

ArrayList实例放在值部分中。

void addValue(Map map, Object key, Object value) {
    Object obj = map.get(key);
    List list;
    if (obj == null) {  
        list = new ArrayList<Object>();  
    } else {
        list = ((ArrayList) obj);
    }
    list.add(value);
    map.put(key, list);
}

有关详细信息,请查看this

答案 3 :(得分:2)

您不应忽略通用参数。你拥有的是

Map<String, Integer> map = new HashMap<>();

如果您想自己编写解决方案,则需要

Map<String, List<Integer>> map = new HashMap<>();

无论如何,优先使用的方法是使用Guava Multimap

答案 4 :(得分:0)

使用带有值类型的Map作为值列表。例如,在地图中,在添加条目时,您将把键设置为“a”,并且您必须将其值作为Integer列表添加,包含所有值所需的值,如1,2,3,4。

答案 5 :(得分:0)

对于包含相同键的条目的地图,无意使用get()。但只要您使用iterator()entrySet(),这应该有效:

class HashMap<String, String> {

  Set<Entry<String, String>> entries;
  @Override
  public Set<Entry<String, String>> entrySet() {
    return entries;
  }

  @Override
  public int size() {
    return entries.size();
  }

  public String put(String key, String value) {
    if (entries == null) {
      entries = new AbstractSet<Entry<String, String>>() {

        ArrayList<Entry<String, String>> list = new ArrayList<>();
        @Override
        public Iterator<Entry<String, String>> iterator() {
          return list.iterator();
        }

        @Override
        public int size() {
          return list.size();
        }

        @Override
        public boolean add(Entry<String, String> stringStringEntry) {
          return list.add(stringStringEntry);
        }
      };
    }
    StatusHandler.MyEntry entry = new StatusHandler.MyEntry();
    entry.setKey(key);
    entry.setValue(value);
    entries.add(entry);
    return value;
  }
};

TL; DR那么,它有什么用呢?这来自于redmine-java-api的hack接受基于表单参数的复杂查询:

https://stackoverflow.com/a/18358659/848072

https://github.com/albfan/RedmineJavaCLI/commit/2bc51901f2f8252525a2d2258593082979ba7122