Java 将重复的键放入 HashMap 时会发生什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1669885/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What happens when a duplicate key is put into a HashMap?
提问by boodieye
If I pass the same key multiple times to HashMap
's put
method, what happens to the original value? And what if even the value repeats? I didn't find any documentation on this.
如果我多次将相同的键传递给HashMap
'sput
方法,原始值会发生什么变化?如果甚至该值重复呢?我没有找到任何关于此的文档。
Case 1: Overwritten values for a key
案例 1:覆盖某个键的值
Map mymap = new HashMap();
mymap.put("1","one");
mymap.put("1","not one");
mymap.put("1","surely not one");
System.out.println(mymap.get("1"));
We get surely not one
.
我们得到surely not one
。
Case 2: Duplicate value
案例 2:重复值
Map mymap = new HashMap();
mymap.put("1","one");
mymap.put("1","not one");
mymap.put("1","surely not one");
// The following line was added:
mymap.put("1","one");
System.out.println(mymap.get("1"));
We get one
.
我们得到one
。
But what happens to the other values? I was teaching basics to a student and I was asked this. Is the Map
like a bucket where the last value is referenced (but in memory)?
但是其他值会发生什么?我正在向一名学生教授基础知识,有人问我这个问题。是不是Map
引用了最后一个值的桶(但在内存中)?
回答by jheddings
By definition, the put
command replaces the previous value associated with the given key in the map (conceptually like an array indexing operation for primitive types).
根据定义,该put
命令替换与映射中给定键关联的先前值(概念上类似于原始类型的数组索引操作)。
The map simply drops its reference to the value. If nothing else holds a reference to the object, that object becomes eligible for garbage collection. Additionally, Java returns any previous value associated with the given key (or null
if none present), so you can determine what was there and maintain a reference if necessary.
映射只是删除对值的引用。如果没有其他对象持有对该对象的引用,则该对象有资格进行垃圾回收。此外,Java 返回与给定键关联的任何先前值(或者null
如果不存在),因此您可以确定那里有什么并在必要时维护引用。
More information here: HashMap Doc
更多信息:HashMap Doc
回答by Pascal Thivent
You may find your answer in the javadoc of Map#put(K, V)(which actually returns something):
你可以在Map#put(K, V)的 javadoc 中找到你的答案(它实际上返回了一些东西):
public V put(K key, V value)
Associates the specified value with the specified key in this map (optional operation). If the map previously contained a mapping for this key, the old value is replaced by the specified value. (A map
m
is said to contain a mapping for a keyk
if and only ifm.containsKey(k)
would returntrue
.)Parameters:
key
- key with which the specified value is to be associated.value
- value to be associated with the specified key.Returns:
previous value associated with specified key, ornull
if there was no mapping forkey
. (Anull
return can also indicate that the map previously associatednull
with the specifiedkey
, if the implementation supportsnull
values.)
public V put(K key, V value)
将指定值与此映射中的指定键相关联(可选操作)。如果映射先前包含此键的映射,则旧值将替换为指定值。(一个映射
m
被称为包含一个键的映射,k
当且仅当它m.containsKey(k)
会返回true
。)参数:
key
- 与指定值相关联的键。value
- 与指定键相关联的值。返回:
与指定键关联的先前值,或者null
如果没有映射key
。(如果实现支持值,null
返回也可以指示先前null
与指定的关联的映射。)key
null
So if you don't assign the returned value when calling mymap.put("1", "a string")
, it just becomes unreferenced and thus eligible for garbage collection.
因此,如果您在调用 时不分配返回值mymap.put("1", "a string")
,它就会变为未引用并因此有资格进行垃圾收集。
回答by Atmocreations
To your question whether the map was like a bucket: no.
对于您的问题,地图是否像一个水桶:不。
It's like a list with name=value
pairs whereas name
doesn't need to be a String (it can, though).
它就像一个带有name=value
成对的列表,而name
不必是一个字符串(尽管它可以)。
To get an element, you pass your key to the get()-method which gives you the assigned object in return.
要获取一个元素,您需要将您的密钥传递给 get() 方法,该方法会返回分配给您的对象。
And a Hashmap means that if you're trying to retrieve your object using the get-method, it won't compare the real object to the one you provided, because it would need to iterate through its list and compare() the key you provided with the current element.
而一个哈希地图意味着,如果你想使用Get-方法来检索您的对象,也不会比较真实的对象提供给您的一个,因为它会通过其名单需要遍历和比较()的关键您提供了当前元素。
This would be inefficient. Instead, no matter what your object consists of, it calculates a so called hashcode from both objects and compares those. It's easier to compare two int
s instead of two entire (possibly deeply complex) objects. You can imagine the hashcode like a summary having a predefined length (int), therefore it's not unique and has collisions. You find the rules for the hashcode in the documentation to which I've inserted the link.
这将是低效的。相反,无论您的对象由什么组成,它都会从两个对象中计算出所谓的哈希码并进行比较。比较两个int
s 而不是两个完整的(可能非常复杂的)对象更容易。您可以将哈希码想象为具有预定义长度 (int) 的摘要,因此它不是唯一的并且存在冲突。您可以在我插入链接的文档中找到哈希码的规则。
If you want to know more about this, you might wanna take a look at articles on javapractices.comand technofundo.com
如果您想了解更多关于这一点,你可能想看看文章对javapractices.com和technofundo.com
regards
问候
回答by kamlesh0606
The prior value for the key is dropped and replaced with the new one.
键的先前值被删除并替换为新值。
If you'd like to keep all the values a key is given, you might consider implementing something like this:
如果您想保留给定键的所有值,您可以考虑实现如下内容:
import org.apache.commons.collections.MultiHashMap;
import java.util.Set;
import java.util.Map;
import java.util.Iterator;
import java.util.List;
public class MultiMapExample {
public static void main(String[] args) {
MultiHashMap mp=new MultiHashMap();
mp.put("a", 10);
mp.put("a", 11);
mp.put("a", 12);
mp.put("b", 13);
mp.put("c", 14);
mp.put("e", 15);
List list = null;
Set set = mp.entrySet();
Iterator i = set.iterator();
while(i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
list=(List)mp.get(me.getKey());
for(int j=0;j<list.size();j++)
{
System.out.println(me.getKey()+": value :"+list.get(j));
}
}
}
}
回答by sheepiiHD
I always used:
我一直使用:
HashMap<String, ArrayList<String>> hashy = new HashMap<String, ArrayList<String>>();
if I wanted to apply multiple things to one identifying key.
如果我想将多项内容应用于一个识别键。
public void MultiHash(){
HashMap<String, ArrayList<String>> hashy = new HashMap<String, ArrayList<String>>();
String key = "Your key";
ArrayList<String> yourarraylist = hashy.get(key);
for(String valuessaved2key : yourarraylist){
System.out.println(valuessaved2key);
}
}
you could always do something like this and create yourself a maze!
你总是可以做这样的事情,为自己创造一个迷宫!
public void LOOK_AT_ALL_THESE_HASHMAPS(){
HashMap<String, HashMap<String, HashMap<String, HashMap<String, String>>>> theultimatehashmap = new HashMap <String, HashMap<String, HashMap<String, HashMap<String, String>>>>();
String ballsdeep_into_the_hashmap = theultimatehashmap.get("firststring").get("secondstring").get("thirdstring").get("forthstring");
}
回答by SatyaS
HashMap<Emp, Emp> empHashMap = new HashMap<Emp, Emp>();
empHashMap.put(new Emp(1), new Emp(1));
empHashMap.put(new Emp(1), new Emp(1));
empHashMap.put(new Emp(1), new Emp());
empHashMap.put(new Emp(1), new Emp());
System.out.println(empHashMap.size());
}
}
class Emp{
public Emp(){
}
public Emp(int id){
this.id = id;
}
public int id;
@Override
public boolean equals(Object obj) {
return this.id == ((Emp)obj).id;
}
@Override
public int hashCode() {
return id;
}
}
OUTPUT : is 1
Means hash map wont allow duplicates, if you have properly overridden equals and hashCode() methods.
意味着哈希映射将不允许重复,如果您正确覆盖了 equals 和 hashCode() 方法。
HashSet also uses HashMap internally, see the source doc
HashSet 也在内部使用 HashMap,请参阅源文档
public class HashSet{
public HashSet() {
map = new HashMap<>();
}
}
回答by BufBills
BTW, if you want some semantics such as only put if this key is not exist. you can use concurrentHashMap
with putIfAbsent()
function.
Check this out:
顺便说一句,如果您想要一些语义,例如仅在此键不存在时才放置。您可以使用concurrentHashMap
withputIfAbsent()
功能。看一下这个:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html#put(K,%20V)
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html#put(K,%20V)
concurrentHashMap
is thread safe with high performance since it uses "lock striping" mechanism to improve the throughput.
concurrentHashMap
由于它使用“锁条带化”机制来提高吞吐量,因此具有高性能的线程安全性。
回答by java acm
it's Key/Value feature and you could not to have duplicate key for several values because when you want to get the actual value which one of values is belong to entered key
in your example when you want to get value of "1" which one is it ?!
that's reasons to have unique key for every value but you could to have a trick by java standard lib :
它是键/值功能,您不能有多个值的重复键,因为当您想获取实际值时,
当您想获取“1”的值时,哪个值属于您的示例中输入的键它 ?!
这就是为每个值设置唯一键的原因,但您可以通过 java 标准库获得一个技巧:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class DuplicateMap<K, V> {
private Map<K, ArrayList<V>> m = new HashMap<>();
public void put(K k, V v) {
if (m.containsKey(k)) {
m.get(k).add(v);
} else {
ArrayList<V> arr = new ArrayList<>();
arr.add(v);
m.put(k, arr);
}
}
public ArrayList<V> get(K k) {
return m.get(k);
}
public V get(K k, int index) {
return m.get(k).size()-1 < index ? null : m.get(k).get(index);
}
}
and you could to use it in this way:
你可以这样使用它:
public static void main(String[] args) {
DuplicateMap<String,String> dm=new DuplicateMap<>();
dm.put("1", "one");
dm.put("1", "not one");
dm.put("1", "surely not one");
System.out.println(dm.get("1"));
System.out.println(dm.get("1",1));
System.out.println(dm.get("1", 5));
}
and result of prints are :
和打印的结果是:
[one, not one, surely not one]
not one
null
回答by ajaynakrani
Yes, this means all the 1 keys with value are overwriten with the last added value and here you add "surely not one" so it will display only "surely not one".
是的,这意味着所有具有值的 1 键都被最后添加的值覆盖,在这里您添加“肯定不是一个”,因此它只会显示“肯定不是一个”。
Even if you are trying to display with a loop, it will also only display one key and value which have same key.
即使您尝试循环显示,它也只会显示具有相同键的一个键和值。
回答by Diego Alejandro
Associates the specified value with the specified key in this map. If the map previously contained a mapping for the key, the old value is replaced.
将指定值与此映射中的指定键相关联。如果映射先前包含键的映射,则旧值将被替换。