将重复键放入HashMap时会发生什么?
如果我多次将相同的密钥传递给HashMap
的put
方法,原始值会发生什么变化? 而且,如果价值重复呢? 我没有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<>(); } }