HashMap的put方法返回值问题
API文档中的描述:

先看一个例子
Map<Character, Integer> map = new HashMap<Character, Integer>();
System.out.println(map.put('a', 0)); // null
System.out.println(map.put('a', 1)); //
System.out.println(map.put('a', 2)); //
System.out.println(map.put('b', 1)); // null
System.out.println(map.put('b', 2)); //
System.out.println(map.get('a')); //
可以看出:put方法的返回值为null或value;
调用put方法时,如果已经存在一个相同的key, 则返回的是前一个key对应的value,同时该key的新value覆盖旧value;
如果是新的一个key,则返回的是null;
通过hashmap的源码可以看出:
map中一个映射不能包含重复的键。每个键最多只能映射一个值。即相同的key在Map中只会有一个与之关联的value存在。
put()方法实现:首先使用hash(key)得到key的hashcode(),hashmap根据获得的hashcode找到要插入的位置所在的链,在这个链里面放的都是hashcode相同的Entry键值对,
在找到这个链之后,会通过equals()方法判断是否已经存在要插入的键值对,而这个equals比较的就是key。
添加对应的key-value这样的键值对node时,如果原本已经存在相同的key,则直接改变对应的value,并返回旧的value;如果不存在相同的key,则插入,在插入链表时,如果链表长度为临界长度TREEIFY_THRESHOLD,再插入任何元素就要变成红黑树。
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);//put方法调用putVal方法
}
/**
* Implements Map.put and related methods
*
* @param hash hash for key
* @param key the key
* @param value the value to put
* @param onlyIfAbsent if true, don't change existing value
* @param evict if false, the table is in creation mode.
* @return previous value, or null if none
*/
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key //key已经存在
V oldValue = e.value; //将已经存在的结点e的value值赋给oldValue
if (!onlyIfAbsent || oldValue == null)//当onlyIfAbsent为false或者oldValue为null时,进行覆盖操作
e.value = value;//覆盖原结点的value值,用新值替换旧值
afterNodeAccess(e);
return oldValue;//返回的是被覆盖的oldValue
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
在hashset中的add方法调用的就是hashmap的put方法,判断put方法的返回值是否等于空,来保证hashset的值不重复。
private transient HashMap<E,Object> map; /**
* Adds the specified element to this set if it is not already present.
* More formally, adds the specified element <tt>e</tt> to this set if
* this set contains no element <tt>e2</tt> such that
* <tt>(e==null ? e2==null : e.equals(e2))</tt>.
* If this set already contains the element, the call leaves the set
* unchanged and returns <tt>false</tt>.
*
* @param e element to be added to this set
* @return <tt>true</tt> if this set did not already contain the specified
* element
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
HashMap的put方法返回值问题的更多相关文章
- Spring MVC--------处理方法返回值的可选类型
对于Spring MVC处理方法支持支持一系列的返回方式: (1)ModelAndView (2)Model (3)ModelMap (4)Map (5)View (6)String (7)Void ...
- C# 方法返回值的个数
方法返回值类型总的来说分为值类型,引用类型,Void 有些方法显示的标出返回值 public int Add(int a,int b) { return a+b; } 有些方法隐式的返回返回值,我们可 ...
- 使用Result代替ResultSet作为方法返回值
在开发过程中,我们不能将ResultSet对象作为方法的返回值,因为Connection连接一旦关闭,在此连接上的会话和在会话上的结果集也将会自动关闭,而Result对象则不会发生这种现象,所以在查询 ...
- AJAX JQuery 调用后台方法返回值(不刷新页面)
AJAX JQuery 调用后台方法返回值(不刷新页面) (1)无参数返回值(本人亲试返回结果不是预期结果) javascript方法: $(function () { //无 ...
- SpringMVC第五篇【方法返回值、数据回显、idea下配置虚拟目录、文件上传】
Controller方法返回值 Controller方法的返回值其实就几种类型,我们来总结一下-. void String ModelAndView redirect重定向 forward转发 数据回 ...
- 关于java字节流的read()方法返回值为int的思考
我们都知道java中io操作分为字节流和字符流,对于字节流,顾名思义是按字节的方式读取数据,所以我们常用字节流来读取二进制流(如图片,音乐 等文件).问题是为什么字节流中定义的read()方法返回值为 ...
- java 反射获取方法返回值类型
//ProceedingJoinPoint pjp //获取方法返回值类型 Object[] args = pjp.getArgs(); Class<?>[] paramsCls = ne ...
- js 获取getElementsTagName()方法返回值的内容
<div id="news-top" class="section"> <h3>Some title</h3> <di ...
- eclipse自动生成变量名声明(按方法返回值为本地变量赋值)
eclipse自动生成变量名声明(按方法返回值为本地变量赋值) ctrl+2+L 这个快捷键可自动补全代码,极大提升编码效率! 注:ctrl和2同时按完以后释放,再快速按L.不能同时按! 比如写这句代 ...
随机推荐
- 菜鸟vimer成长记——第4.2章、编程插件
简介 这部分的插件是与编程相关的插件.主要涉及两大块:所有编程语言通用的插件,以及各个语言独有的插件.插件的数量和合理性,这可能是一个不断累积和修正的过程. 个人感觉,现在比较适合sh,html,ma ...
- (webapp)微信和safri 对于html5 部分功能不兼容,多选或单选下拉框去除边框无效果。
1 appearance:none; 2 -moz-appearance:none; /* Firefox */ 3 -webkit-appearance:none; /* Safari 和 Chro ...
- 发现一个很N且免费的html5拓扑图 关系图 生成组件
传送门:http://visjs.org/ demo代码 <!doctype html> <html> <head> <title>vis.js new ...
- 通过切换iframe来定位元素(用于Python+selenium自动化测试)
切换 iframe:1.由于登录按钮是在iframe上,所以第一步需要把定位器切换到iframe上2.用switch_to_frame方法切换,此处有id属性,可以直接用id定位切换 iframe 与 ...
- [环境配置]Ubuntu16.04下编译安装gcc6.3.0
上一篇的SVS要用gcc6.3编译,否则结果不正确,本来以为gcc很好装,结果发现用apt-get安装gcc6只能安装6.5版本,代码作者奇特的要求只能用gcc6.3,没办法只能用源码装了,期间碰见了 ...
- 启动docker 端口映射时IPV4无法使用
CentOS7 Docker启动一个web服务,使用端口映射报错: WARNING: IPv4 forwarding is disabled. Networking will not work. 查找 ...
- 【Docker】第五篇 Docker 数据管理
一.基本介绍 数据管理的原因:Docker中的容器一旦删除,容器本身的rootfs文件系统就会被删除,容器中的所有数据就会被删除.为了对一些需要持久化的数据,不随容器删除而删除,所以我们可以通过多个容 ...
- 欧拉筛——$O(n)$复杂度的质数筛法
欧拉筛法可以以\(O(n)\)的时间,空间复杂度求出\(1-n\)范围内的所有质数. 其核心思想是每个合数仅会被其最小的质因数筛去一次. See this website for more detai ...
- 2013第四届蓝桥杯C/C++ B组
题目标题: 高斯日记:Excel 大数学家高斯有个好习惯:无论如何都要记日记. 他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210 后来人们知道,那个整数就是日期,它表示 ...
- [linux] lsyncd同步工具
环境说明: 192.168.56.101 同步源 192.168.56.102 同步目标 操作系统centos 7 lsyncd项目地址:https://github.com/axkibe/lsync ...