将重复键放入HashMap时会发生什么?

如果我多次将相同的密钥传递给HashMapput方法,原始值会发生什么变化? 而且,如果价值重复呢? 我没有find任何文件。

情况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")); 

我们surely not one

情况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")); 

我们得到one

但是其他的价值呢? 我正在向一名学生讲授基础知识,并被问到这一点。 Map像最后一个值被引用的桶(但在内存中)?

根据定义, put命令将replace与映射中给定键相关的先前值(概念上类似于原始types的数组索引操作)。

地图只是将其引用的值删除。 如果没有别的东西持有对该对象的引用,那么该对象就有资格进行垃圾回收。 此外,Java返回与给定键相关的任何以前的值(如果没有,则返回null ),所以您可以确定在那里有什么并在必要时保留引用。

更多信息在这里: HashMap Doc

你可以在Map#put(K,V)的javadoc中find你的答案(实际上它返回了一些东西):

 public V put(K key, V value) 

将指定的值与此映射中指定的键关联(可选操作)。 如果映射先前包含该键的映射,则旧值由指定值replace。 (当且仅当m.containsKey(k)将返回true映射m才被认为包含关键k的映射。)

参数:
key – 与指定值相关联的键。
value – 要与指定键相关联的值。

返回:
先前与指定键相关联的null如果没有key映射,则返回null 。 (如果实现支持null值,则null返回也可以指示映射先前将null与指定的key关联。

因此,如果在调用mymap.put("1", "a string")时不指定返回的值,它就会变成未被引用的,从而有资格进行垃圾回收。

密钥的先前值将被丢弃,并replace为新密钥。

如果你想保留一个关键的所有值,你可以考虑实现这样的事情:

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

这是键/值function,你不能有多个值的重复键,因为当你想获得实际值哪一个值属于input的密钥
在你的例子中,当你想得到“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); } } 

你可以这样使用它:

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

打印结果是:

 [one, not one, surely not one] not one null 

将指定的值与此映射中指定的键关联。 如果映射先前包含该键的映射, 则replace旧值。

对于你的问题,地图是否像一个桶:不。

这就像name=value对的名单,而name不需要是一个string(它可以,虽然)。

为了得到一个元素,你把你的密钥传递给get()方法,该方法返回给你指定的对象。

哈希表意味着如果你试图用get方法检索你的对象,它不会比较你提供的对象和实际对象,因为它需要迭代它的列表并且比较()关键字你提供了当前的元素。

这将是低效的。 相反,不pipe你的对象是由哪个对象组成,它都会从这两个对象中计算出一个所谓的哈希码,然后比较它们。 比较两个int而不是两个完整的(可能是非常复杂的)对象更容易。 你可以把hashcode想象成一个具有预定义长度(int)的摘要,因此它不是唯一的并且有冲突。 您可以在我插入链接的文档中find哈希码的规则。

如果你想更多地了解这个,你可能想看看关于javapractices.com和technofundo.com的文章

问候

我一直使用:

 HashMap<String, ArrayList<String>> hashy = new HashMap<String, ArrayList<String>>(); 

如果我想将多个东西应用于一个识别密钥。

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

你总是可以做这样的事情,创造一个迷宫!

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

顺便说一句,如果你想要一些语义,如只有把这个关键不存在。 你可以使用带有putIfAbsent()函数的concurrentHashMap 。 看一下这个:

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html#put(K,%20V);

由于使用“ 锁条 ”机制来提高吞吐量,因此concurrentHashMap具有高性能的线程安全性。

是的,这意味着所有有价值的键都被最后一次添加的值覆盖,在这里添加“当然不是一个”,所以它只会显示“肯定不是一个”。

即使你试图用循环显示,它也只会显示一个键和值相同的键。

  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 

意思是哈希映射不会允许重复,如果你已经正确地重写equals和hashCode()方法。

HashSet也在内部使用HashMap,请参阅源文档

 public class HashSet{ public HashSet() { map = new HashMap<>(); } }