Java - 如何在不覆盖现有HashMap键的情况下向其添加另一个字符串值?

16

我想知道是否有人能帮忙解决在Java中向HashMap的现有键添加另一个String值的问题?

我知道可以使用this.put("String", "String")方法添加键-值对。然而,它会覆盖现有的值,而我希望同一键下存储和配对多个值。

谢谢您的帮助。


编写自己的自定义类,其中String将是您的实例变量,并覆盖equals和hashcode方法并使用它,以您的方式。我的问题是,您为什么要这样做? - Sashi Kant
“在Java中的HashMap中将另一个字符串值添加到现有键中”这个问题不是很清楚。map.put("foo","bar"); map.put("foo","bar")的结果应该是什么?键“foo”的值应该是什么?它应该是"barbar",还是类似于列表"[bar, bar]",或者您只想要唯一的值,因此它仍然应该是"bar"? - Pshemo
9个回答

25

你希望在这里实现什么目标?

在你的情况下,Map(即HashMap)是一种直接从一个“键”映射到另一个值的方式。

例如:

"foo" -> 123
"bar" -> 321
"far" -> 12345
"boo" -> 54321

这意味着如果你尝试:

myHashMap.get("foo");

它将返回值123(当然,你返回的值的类型可以是任何东西)。

当然,这也意味着,对于键的值所做的任何更改都会覆盖您分配给它的原始值,就像更改变量的值会覆盖原始值一样。

例如:

myHashMap.put("foo", 42);

在地图中,"foo" 的旧值将被替换为 42。因此它会变成:

"foo" -> 42
"bar" -> 321
"far" -> 12345
"boo" -> 54321
然而,如果您需要将多个从单个键映射的String对象,则可以使用另一个可以存储多个对象的对象,例如Array或List(甚至是另一个HashMap如果您想要的话)。
例如,如果您要使用ArrayLists,当您为HashMap分配值时(假设它称为myHashMap),您首先会检查是否以前已经使用过该键。 如果没有,则创建一个新的ArrayList与要添加的值一起,如果有,则只需将该值添加到列表中。
(假设keyvalue具有您想要的值)
ArrayList<String> list;
if(myHashMap.containsKey(key)){
    // if the key has already been used,
    // we'll just grab the array list and add the value to it
    list = myHashMap.get(key);
    list.add(value);
} else {
    // if the key hasn't been used yet,
    // we'll create a new ArrayList<String> object, add the value
    // and put it in the array list with the new key
    list = new ArrayList<String>();
    list.add(value);
    myHashMap.put(key, list);
}

18

你可以像这样做!

Map<String,List<String>> map = new HashMap<>();
.
.
if(map.containsKey(key)){
    map.get(key).add(value);
} else {
   List<String> list = new ArrayList<>();
   list.add(value);
   map.put(key, list);
}

或者您可以使用Java 8风格的一行代码来完成同样的事情。

map.computeIfAbsent(key, k ->new ArrayList<>()).add(value);

第一种方法并不适用于所有情况。您没有将更新后的值分配回映射表。 - saran3h

5
您需要将这两个字符串拼接在一起吗?
map.put(key, val);
if (map.containsKey(key)) {
    map.put(key, map.get(key) + newVal);
}

或者您想要列出该键的所有值的列表吗?
HashMap<String,List<String>> map = new HashMap<String,List<String>>();
String key = "key";
String val = "val";
String newVal = "newVal";
List<String> list = new ArrayList<String>();
list.add(val);
map.put(key, list);
if (map.containsKey(key)) {
    map.get(key).add(newVal);
}

3
正如其他人所指出的,按照规范,Map 对于给定的键只能有一个值。你有两个解决方案:
  • 使用 HashMap<String, List<String>> 存储数据
  • 使用第三方 Google Collections 库提供的 Multimap

1

地图接口文档所述,Map包含一组键,因此不能包含多个非唯一键。

我建议您将列表用作此地图的值。


0

你不能直接在单个键下存储多个值,但与键关联的值可以是任何类型的对象,例如一个ArrayList,它将容纳多个值。例如:

import java.util.ArrayList;
import java.util.HashMap;

public class HashMapList {
    HashMap<String, ArrayList<String>> strings = new HashMap<String, ArrayList<String>>();

    public void add(String key, String value) {
        ArrayList<String> values = strings.get(key);
        if (values == null) {
            values = new ArrayList<String>();
            strings.put(key, values);
        }

        values.add(value);
    }

    public ArrayList<String> get(String key) {
        return strings.get(key);
    }

    public static void main(String[] argv) {
        HashMapList mymap = new HashMapList();

        mymap.add("key", "value1");
        mymap.add("key", "value2");

        ArrayList<String> values = mymap.get("key");
        for (String value : values) {
            System.out.println(value);
        }
    }
}

0

将值存储为映射下的列表,因此如果键是test并且有两个值val1和val2,则键将是test,值将是包含val1和val2的列表

但是,如果您的意图是为同一键具有两个单独的条目,则Map不是为此设计的。想想如果您执行map.get("key"),您期望哪个值


0
你可以使用 Map<String, Collection<String>>,但是添加和删除值会很麻烦。更好的方法是使用 guava Multimap - 一个容器,允许为每个键存储多个值。

-1

这是不可能的,因为如果您将String作为map的键,相同的键会具有相同的哈希码值,而String是不可变的。


1
被哈希的是键,而不是值。 - EvenLisle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接