HashMap 和 HashSet
对于HashSet而言,系统采用Hash算法决定集合元素的存储位置,这样可以保证快速存取集合元素;
对于HashMap,系统将value当成key的附属,系统根据Hash算法来决定key的存储位置,这样可以保证快速存取集合key,而value总是紧随key存储。
(这些集合虽然号称存储的是java对象,但实际上并不会真正将java对象放入set集合中,而只是在Set集合中保留这些对象的引用。
当程序视图将多个key-value 放入HashMap中时,采用一种“Hash算法”来决定每个元素的存储位置。
1 public V put(K key, V value)
2 {
3 if(key == null)
4 return putForNullKey(value);
5 int hash = hash(key.hashCode());
6
7 int i = indexFor(hash, table.length);
8
9 for(Entry<K,V> e = table[i]; e!=null;e=e.next)
10 {
11 Object K;
12 if(e.hash==hash && ((k=e.key) == k || key.equals(k))
13 {
14 V oldValue = e.value;
15 e.value= value;
16 e.recordAccess(this);
17 return oldValue;
18 }
19 }
20 modCount ++;
21 addEnrty(hash,key,value,i);
22 return null;
23 }
一个重要的内部接口Map.Entry,每个Map.Entry其实就是一个Key-Value对。当系统决定存储HashMap中的key-value对是,只是根据key来计算并决定每个Entry的存储位置:如果两个Entry的key的hashCode()返回值相同,那么它们的存储位置相同;如果这两个key通过equals比较返回true,新添加的Entry的value将覆盖原有Entry的value,但key不会覆盖;如果这两个key通过equals比较返回false,新添加的Entry将与集合中原有Entry形成Entry链。见addEntry()方法:
1 void addEntry(int hash,K key,V value,int bucketIndex)
2 {
3 Entry<K,V> e = table[bucketIndex];
4 table[bucketIndex] = new Entry<K,V>(hash,key,value,e);
5 if(size++ >= threshold) //threshold包含HashMap能容纳的key-value对的极限。
6 resize(2*table.length);
7 }
table实质就是一个普通数组,每个数组都有一个固定一的长度,这个数组的长度就是HashMap的容量。
HashSet是基于HashMap实现的,HashSet底层采用HashMap来保存所有元素。
1 class Name
2 {
3 private String first;
4 private String last;
5 public Name(String first, String last)
6 {
7 this.first = first;
8 this.last = last;
9 }
10 public boolean equals(Object o)
11 {
12 if(this == o)
13 return true;
14 if(o.getClass() == Name.class)
15 {
16 Name n =(Name) o;
17 return n.first.equals(first) && n.last.equals(last);
18 }
19 return false;
20 }
21
22 public class HashSetTest
23 {
24 public static void main(String[] args)
25 {
26 Set<Name> s = new HashSet<Name>();
27 s.add(new Name("abc","123"));
28 System.out.println(s.contains(new Name("abc","123");
29 }
30 }
31
运行结果是false.
因为HashSet判断两个对象相等的标准除了要求通过equals方法比较返回true外,还要求两个对象的hashCode()返回值相等。
重写hashCode()方法:
public int hashCode()
{
return first.hashCode();
}
public boolean equals(Object o)
{
....
if(o.getClass() == Name.class)
{
Name n = (Name) o;
return n.first.equals(first);
}
...
}
HashMap 和 HashSet的更多相关文章
- HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别
①HashMap的工作原理 HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象.当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算h ...
- 谁可以说出HashMap和HashSet的相同点和不同点。
谁可以说出HashMap和HashSet的相同点和不同点. 2011-11-15 20:46ruoshui_t | 浏览 20310 次 Perl 2011-11-15 21:17 #知道行家专业创 ...
- [转] HashMap和HashSet的区别
HashMap和HashSet的区别是Java面试中最常被问到的问题.如果没有涉及到Collection框架以及多线程的面试,可以说是不完整.而Collection框架的问题不涉及到HashSet和H ...
- HashMap和HashSet的区别
理解HashSet及使用 HashMap和HashSet的区别是Java面试中最常被问到的问题.如果没有涉及到Collection框架以及多线程的面试,可以说是不完整.而Collection框架的问题 ...
- [置顶] HashMap HashTable HashSet区别剖析
HashMap.HashSet.HashTable之间的区别是Java程序员的一个常见面试题目,在此仅以此博客记录,并深入源代码进行分析: 在分析之前,先将其区别列于下面 1:HashSet底层采用的 ...
- HashMap、HashSet源代码分析其 Hash 存储机制
集合和引用 就像引用类型的数组一样,当我们把 Java 对象放入数组之时,并不是真正的把 Java 对象放入数组中,只是把对象的引用放入数组中,每个数组元素都是一个引用变量. 实际上,HashSet ...
- HashMap HashTable HashSet
原文转载自 http://blog.csdn.net/wl_ldy/article/details/5941770 HashMap是新框架中用来代替HashTable的类 也就是说建议使用HashMa ...
- 【转】HashMap和HashSet的区别
原文网址:http://www.importnew.com/6931.html HashMap和HashSet的区别是Java面试中最常被问到的问题.如果没有涉及到Collection框架以及多线程的 ...
- HashMap HashTable HashSet区别剖析
HashMap.HashSet.HashTable之间的区别是Java程序员的一个常见面试题目,在此仅以此博客记录,并深入源代码进行分析: 在分析之前,先将其区别列于下面 1:HashSet底层采用的 ...
- java该HashTable,HashMap和HashSet
同一时候我们也对HashSet和HashMap的核心方法hashcode进行了具体解释,见<探索equals()和hashCode()方法>. 万事俱备,那么以下我们就对基于hash算法的 ...
随机推荐
- RabbitMQ保证消息的顺序性
当我们的系统中引入了MQ之后,不得不考虑的一个问题是如何保证消息的顺序性,这是一个至关重要的事情,如果顺序错乱了,就会导致数据的不一致. 比如:业务场景是这样的:我们需要根据mysql的b ...
- Django笔记&教程 5-3 综合使用示例
Django 自学笔记兼学习教程第5章第3节--综合使用示例 点击查看教程总目录 1 - 生成学号场景 场景描述: 教务管理系统中,学生注册账号,学生选择年级后,生成唯一学号. 细节分析: 学生学号由 ...
- jenkins bat删除指定路径下的文件及文件夹
最近在用jenkins集成,生成allure测试报告,但是每次生成的allure测试报告,都是上一次执行的痕迹.比如这次我只运行了100个用例,结果显示运行2000条,上一次运行的用例,时间也涵括了上 ...
- (数据科学学习手札131)pandas中的常用字符串处理方法总结
本文示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 在日常开展数据分析的过程中,我们经常需要对 ...
- [atARC121F]Logical Operations on Tree
(特判$n=1$的情况) 当确定权值和操作后,如何判定是否合法-- 考虑一个度为1的节点,对其权值即其对应边的边操作分类讨论: $1\or$,显然只需要最后选择这条边即可,一定合法 $1\and$或$ ...
- 使用国内的镜像源搭建 kubernetes(k8s)集群
1. 概述 老话说的好:努力学习,提高自己,让自己知道的比别人多,了解的别人多. 言归正传,之前我们聊了 Docker,随着业务的不断扩大,Docker 容器不断增多,物理机也不断增多,此时我们会发现 ...
- mybatis-批量操作数据(list对象 )
在实际工作中老是忘记 传入的参数和数据库参数名称要一致还是与实体类型一致导致很多笑话发生. 那我还是做个记录吧! dao层: int addRemark(@Param("list" ...
- Codeforces 1500D - Tiles for Bathroom(贪心+队列)
Codeforces 题面传送门 & 洛谷题面传送门 首先先讲一发我的 \(n^2q\log n\) 的做法,虽然没有付诸实现并且我也深知它常数巨大过不去,但是我还是决定讲一讲(大雾 考虑设 ...
- Codeforces 505E - Mr. Kitayuta vs. Bamboos(二分+堆)
题面传送门 首先很显然的一点是,看到类似于"最大值最小"的字眼就考虑二分答案 \(x\)(这点我倒是想到了) 然鹅之后就不会做了/wq/wq/wq 注意到此题正着处理不太方便,故考 ...
- 洛谷 P7324 - [WC2021] 表达式求值(状压+dp)
题面传送门 现场人傻系列-- 首先建出 \(E\) 的表达式树,具体来说表达式的每一个叶子节点表示一个数组 \(A_i\),每一个非叶子节点都表示一次运算,它的值表示左右儿子进行该运算后得到的结果.这 ...