What happens when a duplicate key is put into a HashMap?
如果我多次将相同的密钥传递给
案例1:密钥的覆盖值
1 2 3 4 5 |
我们得到
案例2:重复值
1 2 3 4 5 6 7 |
我们得到
但是其他价值观会发生什么? 我正在向学生教授基础知识,我被问到这个问题。
根据定义,
地图只是删除了对值的引用。如果没有其他内容包含对该对象的引用,则该对象将有资格进行垃圾回收。此外,Java返回与给定键关联的任何先前值(如果不存在,则返回
更多信息:HashMap Doc
您可以在Map#put(K,V)的javadoc中找到答案(实际上返回了一些内容):
1
2 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 mapm 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.)
因此,如果在调用
键的先前值将被删除并替换为新值。
如果您希望保留所有值,则可以考虑实现以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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)); } } } } |
它是键/值功能,您不能为多个值设置重复键,因为当您希望得到"1"的值时,如果您希望获得其中一个值属于输入键的实际值,那么就是它?!这是为每个值都有唯一键的原因,但你可以通过java标准库获得一个技巧:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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); } } |
你可以用这种方式使用它:
1 2 3 4 5 6 7 8 9 |
打印结果如下:
1 2 3 | [one, not one, surely not one] not one null |
将指定的值与此映射中的指定键相关联。如果映射先前包含键的映射,则替换旧值。
对于你的问题,地图是否像一个桶:没有。
它就像一个
要获取元素,可以将密钥传递给get() - 方法,该方法为您提供返回的已分配对象。
Hashmap意味着如果您尝试使用get方法检索对象,它将不会将真实对象与您提供的对象进行比较,因为它需要迭代其列表并比较()键您提供当前元素。
这将是低效的。相反,无论您的对象包含什么,它都会从两个对象计算所谓的哈希码并对其进行比较。比较两个
如果您想了解更多相关信息,可以查看javapractices.com和technofundo.com上的文章。
问候
它替换了相应键的映射中的现有值。如果没有具有相同名称的密钥,则它会创建一个具有所提供值的密钥。
例如:
OUTPUT
key ="1",value ="two"
因此,之前的值会被覆盖。
我一直用:
如果我想将多个东西应用于一个识别键。
1 2 3 4 5 6 7 8 9 10 11 |
你可以做这样的事情,创造一个迷宫!
1 2 3 4 | 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"); } |
JDK中的映射不用于在重复键下存储数据。
-
最好的新值将覆盖以前的值。
-
更糟糕的情况是异常(例如,当您尝试将其作为流收集时):
没有重复:
Ok. You will get: $2 ==> {one=one}
重复流:
Exception java.lang.IllegalStateException: Duplicate key 1 (attempted merging values one and not one)
| at Collectors.duplicateKeyException (Collectors.java:133)
| at Collectors.lambda$uniqKeysMapAccumulator$1 (Collectors.java:180)
| at ReduceOps$3ReducingSink.accept (ReduceOps.java:169)
| at Spliterators$ArraySpliterator.forEachRemaining (Spliterators.java:948)
| at AbstractPipeline.copyInto (AbstractPipeline.java:484)
| at AbstractPipeline.wrapAndCopyInto (AbstractPipeline.java:474)
| at ReduceOps$ReduceOp.evaluateSequential (ReduceOps.java:913)
| at AbstractPipeline.evaluate (AbstractPipeline.java:234)
| at ReferencePipeline.collect (ReferencePipeline.java:578)
| at (#4:1)
处理重复密钥 - 使用其他包,例如:
https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Multimap.html
还有很多其他实现处理重复的密钥。
Web需要这些(例如重复的cookie密钥,Http标头可以有相同的字段,......)
祝好运! :)
是的,这意味着所有带有值的1个键都会被最后添加的值覆盖,在这里你添加"肯定不是一个",所以它只显示"肯定不是一个"。
即使您尝试使用循环显示,它也只会显示一个具有相同键的键和值。
顺便说一句,如果你想要一些语义,比如只有当这个键不存在时才放。您可以使用
看一下这个:
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html#put(K,%20V)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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,请参阅源文档