java——HashSet中add()方法不能加重复值得原因理解(我们一起来看底层代码吧)
Set<String> names = new HashSet<>();
names.add("张三");
names.add(new String("张三")); Iterator<String> iterator = names.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
以上代码输出只有一个:张三
惊不惊喜,意不意外???
下面我们来看原因
按住ctrl键点击add进入到public interface Set<E> extends Collection<E> Set接口中的add抽象方法
boolean add(E e);
然后按住ctrl键盘点击到HashSet类中重新的add方法
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
按住ctrl键点击put 进入到HashMap类中的put方法
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
其中的hash(key)是HashMap中的方法
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
返回的值是key.hashCode()的相关转换,我们就看key.hashCode()的值是什么了 那我们来看一下这个方法
public native int hashCode();//是Object类中的一个抽象方法
其中有继承重写这个方法的,但是打开Eclipse就会bug 试了两次了 ,那我们就不打开了
但是我们可以得到一个结论:
本身HashSet中的hashCode()方法就是同一个对象的hashCode()的返回值是相等的
我们可以自己重写hashCode()方法来判断他返回的值
并且其中putVal()方法也在HashMap方法中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;
/*
怎么判断相等的就是用下面的红色代码
p.hash==hash 就是调用hash(key)方法后的值,只要是同一个对象,返回值就相同(可以重写hashCode()方法)
(k = p.key) == key判断两个对象的地址是否相同
key.equals(k)默认调用Object类中的equals方法判断地址是否相同,可以重写equals方法
如果以上满足
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(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
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
分析:为上面青色字体
java——HashSet中add()方法不能加重复值得原因理解(我们一起来看底层代码吧)的更多相关文章
- java Queue中 add/offer,element/peek,remove/poll区别
转自https://blog.csdn.net/u012050154/article/details/60572567 java Queue中 add/offer,element/peek,remov ...
- 用HashSet的add方法谈hashcode和equals方法重写
本文主要通过用HashSet的add方法讲一下hashCode和equals方法重写.错误的地方望指正. 1.了解HashSet的add方法 了解一个方法的好办法是看源码,所以先看源码 private ...
- thymeleaf模板引擎调用java类中的方法(附源码)
前言 <Docker+SpringBoot+Mybatis+thymeleaf的Java博客系统开源啦> 由于开源了项目的缘故,很多使用了My Blog项目的朋友遇到问题也都会联系我去解决 ...
- Jsp中如何通过Jsp调用Java类中的方法
Jsp中如何通过Jsp调用Java类中的方法 1.新建一个项目,在src文件夹下添加一个包:如:cn.tianaoweb.com; 2.再在包中添加一个类:如 package com; public ...
- 【转载】C#中Add方法将往List集合末尾添加相应元素对象
在C#的List集合操作中,有时候需要将符合条件的对象添加到已有List集合中的末尾,此时就需要使用到List集合的Add方法,Add方法的作用为将对应的元素添加到List集合末尾,Add方法签名为v ...
- HashSet的add()方法源码解析(jdk1.8)
HashSet 实现了Set接口 实际上是HashMap 可以存null,但只能有一个 不保证元素是有序的,取决于hash后,在确定索引结果 add源码 //核心操作putVal final V pu ...
- 第6章 Java类中的方法
1.如何定义java的方法 什么是方法:方法使用来解决一类问题的代码集合,是一个功能模块在类中定义个方法的方法是: 访问修饰符 返回值类型 方法名(参数列表){ 方法体 } 1.访问修饰符,是限制该方 ...
- Java接口中的方法
接口中可以含有变量和方法.但是,接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误),而方法 ...
- jsp中怎么调用java类中的方法
在jsp页面中先要,引入java类 例如: <%@page import="javabean.DbConn"%><!-- 引入包中的"类" - ...
随机推荐
- 【零基础】speech driven animation中文安装使用指南
注:原项目名叫Speech-Driven Animation,所以我这里就简称为SDA 开局一张图,后面自动编 相信前段时间爆火的DeepNude(AI扒衣)让很多人惊掉了大牙,AI还能干这个?!如果 ...
- tensorflow feeddict问题unhashable type: 'numpy.ndarray'
https://stackoverflow.com/a/49134587 求argmax.加newaxis.转变data类型时尽量用tf自带的函数: tf.argmax.[tf.newaxis, :] ...
- HearthBuddy炉石兄弟 如何调试ai
Sepefeets's update to botmaker's Silverfish AI This AI is a Custom Class for Hearthranger and Hearth ...
- C++ UFT-8和GB2312间的转换
在这个帖子找到的代码 还蛮好用的 https://bbs.csdn.net/topics/391040755 #include <codecvt> #include <locale& ...
- 基于角色的权限控制系统(role-based access control)
role-based access control(rbac),指对于不同角色的用户,拥有不同的权限 .用户对应一个角色,一个角色拥有若干权限,形成用户-角色-权限的关系,如下图所示.当一个用户进行访 ...
- incredibuild(分布式任务软件)脚本
IncrediBuild 可以在Server段通过修改单个任务的进程上限来实现提升任务执行速度. IncredBuild本机版也可以用来进行本机实现多线程任务分发,这样可以充分利用多核资源. 提交分布 ...
- QQ输入法中英文标点符号快速切换
QQ输入法中英文标点符号快速切换 全角半角切换 shift+ Space 全角半角切换 双击shift 中英文标点符号快速切换 Ctrl+.
- layui-简单的登录注册界面【转载】
register.html 源代码: 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 ...
- 反射中的 Method 的 getReadMethod 与 getWriteMethod 使用 【获取一个对象的所有属性字段名称和其对应的值】
转: class反射(一),以及Method 的 getReadMethod 与 getWriteMethod 使用 2018年11月28日 17:27:42 zich77521 阅读数 788 ...
- Lucence简单学习---1
package cn.itheima.lucene; import java.io.File; import java.util.ArrayList; import java.util.List; i ...