如果我多次把同一把钥匙传给 HashMap
的 put
方法,原值会发生什么变化?如果值重复呢?我没有找到任何关于这个的文件。
情况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
就像引用最后一个值的bucket(但在内存中)?
12条答案
按热度按时间wbgh16ku1#
你可以在map#put(k,v)的javadoc中找到答案(它实际上返回了一些东西):
将指定值与此Map中的指定键相关联(可选操作)。如果Map以前包含此键的Map,则旧值将替换为指定值(Map
m
据说包含一个键的Mapk
当且仅当m.containsKey(k)
会回来的true
.)参数:
key
-与指定值关联的键。value
-要与指定键关联的值。退货:
与指定键关联的上一个值,或
null
如果没有Mapkey
. (一null
return还可以指示先前关联的Mapnull
使用指定的key
,如果实现支持null
值。)如果调用时不赋值
mymap.put("1", "a string")
,它只是变得不可引用,因此符合垃圾收集的条件。jrcvhitl2#
它将替换Map中相应键的现有值。如果不存在具有相同名称的键,那么它将使用提供的值创建一个键。如:
输出键=“1”,值=“2”
因此,前面的值被覆盖。
5w9g7ksd3#
将指定值与此Map中的指定键相关联。如果Map以前包含键的Map,则替换旧值。
nwlls2ji4#
顺便说一句,如果你想要一些语义,比如只有当这个键不存在时才放。你可以用
concurrentHashMap
与putIfAbsent()
功能。看看这个:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/concurrenthashmap.html#put(千伏,%20v)
concurrentHashMap
是线程安全的高性能,因为它使用“锁条带化”机制来提高吞吐量。yws3nbqq5#
来自jdk的Map并不用于在重复的键下存储数据。
新值最多会覆盖以前的值。
更糟糕的情况是异常(例如,当您尝试将其收集为流时):
无重复项:
Stream.of("one").collect(Collectors.toMap(x -> x, x -> x))
好 啊。您将得到:$2==>{one=one}复制流:
Stream.of("one", "not one", "surely not one").collect(Collectors.toMap(x -> 1, x -> x))
exception java.lang.illegalstateexception:在collectors.duplicatekeyexception(collectors)处重复键1(尝试合并一个值而不是一个值)。java:133)|在收集器处。lambda$uniqkeysmapmapacculator$1(收集器。java:180)|在reduceops$3reducesink.accept(reduceops。java:169)|在拆分器$arrayspliterator.foreachremaining处(拆分器。java:948)|在abstractpipeline.copyinto(abstractpipeline。java:484)|在abstractpipeline.wrapandcopyinto(abstractpipeline。java:474)|在reduceops$reduceops.evaluatesequential(reduceops。java:913)|在abstractpipeline.evaluate(abstractpipeline。java:234)|在referencepipeline.collect(referencepipeline。java:578)|在(#4:1)要处理重复的密钥-请使用其他软件包,例如:https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/multimap.html
有许多其他的实现处理重复的密钥。这些是web所需要的(例如,重复的cookie密钥、http头可以有相同的字段,…)
祝你好运!:)
4sup72z86#
意味着哈希Map不允许重复,如果您正确地重写了equals和hashcode()方法。
hashset在内部也使用hashmap,请参阅源文档
watbbzwu7#
是的,这意味着所有带值的1键都被最后添加的值覆盖,在这里您添加了“肯定不是一个”,因此它将只显示“肯定不是一个”。
即使您尝试使用循环显示,它也只会显示一个键和值,它们具有相同的键。
mbyulnm08#
对于你的问题Map是否像一个桶:不。
就像一张有
name=value
成对,鉴于name
不需要是字符串(但是可以)。要获取一个元素,需要将键传递给get()—方法,该方法将返回指定的对象。
hashmap意味着如果您试图使用get方法检索您的对象,它不会将实际对象与您提供的对象进行比较,因为它需要遍历它的list并比较()您提供给当前元素的键。
这将是低效的。相反,不管您的对象由什么组成,它都从这两个对象计算所谓的hashcode并比较它们。比较两者更容易
int
而不是两个完整(可能非常复杂)的对象。您可以将hashcode想象成一个具有预定义长度(int)的摘要,因此它不是唯一的并且有冲突。您可以在我插入链接的文档中找到hashcode的规则。如果您想了解更多这方面的信息,您可能想看看javapractices.com和technofundo.com上的文章
当做
g6baxovj9#
根据定义
put
命令替换与Map中给定键相关联的先前值(概念上类似于基元类型的数组索引操作)。Map只是删除对值的引用。如果没有其他对象包含对该对象的引用,则该对象将有资格进行垃圾收集。此外,java返回与给定键(或
null
如果不存在),则可以确定存在什么,并在必要时保留引用。更多信息:hashmap doc
w6lpcovy10#
键的先前值将被删除并替换为新值。
如果您想保留一个键给定的所有值,可以考虑实现如下内容:
nhjlsmyf11#
我总是用:
如果我想对一个识别键应用多个东西。
你总是可以这样做,给自己制造一个迷宫!
q9yhzks012#
它是键/值特性,您不能为多个值设置重复键,因为当您要获取实际值时,输入的键属于哪一个值
在你的例子中,当你想得到“1”的值时,它是哪一个?!
这就是每个值都有唯一键的原因,但您可以使用java标准库的技巧:
你可以这样使用它:
打印结果如下: