对于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的更多相关文章

  1. HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别

    ①HashMap的工作原理 HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象.当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算h ...

  2. 谁可以说出HashMap和HashSet的相同点和不同点。

    谁可以说出HashMap和HashSet的相同点和不同点. 2011-11-15 20:46ruoshui_t | 浏览 20310 次  Perl 2011-11-15 21:17 #知道行家专业创 ...

  3. [转] HashMap和HashSet的区别

    HashMap和HashSet的区别是Java面试中最常被问到的问题.如果没有涉及到Collection框架以及多线程的面试,可以说是不完整.而Collection框架的问题不涉及到HashSet和H ...

  4. HashMap和HashSet的区别

    理解HashSet及使用 HashMap和HashSet的区别是Java面试中最常被问到的问题.如果没有涉及到Collection框架以及多线程的面试,可以说是不完整.而Collection框架的问题 ...

  5. [置顶] HashMap HashTable HashSet区别剖析

    HashMap.HashSet.HashTable之间的区别是Java程序员的一个常见面试题目,在此仅以此博客记录,并深入源代码进行分析: 在分析之前,先将其区别列于下面 1:HashSet底层采用的 ...

  6. HashMap、HashSet源代码分析其 Hash 存储机制

    集合和引用 就像引用类型的数组一样,当我们把 Java 对象放入数组之时,并不是真正的把 Java 对象放入数组中,只是把对象的引用放入数组中,每个数组元素都是一个引用变量. 实际上,HashSet ...

  7. HashMap HashTable HashSet

    原文转载自 http://blog.csdn.net/wl_ldy/article/details/5941770 HashMap是新框架中用来代替HashTable的类 也就是说建议使用HashMa ...

  8. 【转】HashMap和HashSet的区别

    原文网址:http://www.importnew.com/6931.html HashMap和HashSet的区别是Java面试中最常被问到的问题.如果没有涉及到Collection框架以及多线程的 ...

  9. HashMap HashTable HashSet区别剖析

    HashMap.HashSet.HashTable之间的区别是Java程序员的一个常见面试题目,在此仅以此博客记录,并深入源代码进行分析: 在分析之前,先将其区别列于下面 1:HashSet底层采用的 ...

  10. java该HashTable,HashMap和HashSet

    同一时候我们也对HashSet和HashMap的核心方法hashcode进行了具体解释,见<探索equals()和hashCode()方法>. 万事俱备,那么以下我们就对基于hash算法的 ...

随机推荐

  1. linux堡垒机下定位日志文件内容

    查找关键词grep 命令: grep '关键字' 文件 --color 功能:搜素文件内容 语法: grep [-iv] 关键字 文件 -i 不区分大小写 -v 忽略指定字符串 -n 显示行号 -C ...

  2. 解决虚拟机linux系统全屏问题

    修改设置 1) 如下图右单击虚拟机名,选择[settings-],调出虚拟机设置界面. 2) 在设置界面选择[hardware]->[CD/DVD2(IDE)]->[Connection] ...

  3. sklearn之转换器和估计器

    sklearn之转换器和估计器 转换器 估计器(sklearn机器学习算法的实现) 转换器 想一下之前做的特征工程的步骤? 实例化(实例化的是一个转换器类(Transformer)--特征工程的父类) ...

  4. 如何保证redis中存放的都是热点数据

    当redis使用的内存超过了设置的最大内存时,会触发redis的key淘汰机制,在redis 3.0中有6种淘汰策略: noeviction: 不删除策略.当达到最大内存限制时, 如果需要使用更多内存 ...

  5. Part 18 $http service in AngularJS

    In Angular there are several built in services. $http service is one of them. In this video, we will ...

  6. Java 如何对文件进行多个Object对象流的读写操作

    思路:把已经序列化的对象存入容器(如LinkedList<?>)中,然后用ObjectInputStream和ObjectOutputStream对这个实例化的LinkedList< ...

  7. [cf1495F]Squares

    令$nex_{i}=\min_{i<j,p_{i}<p_{j}}j$(即$i$的第2类边),若不存在此类$j$则$nex_{i}=n+1$ 建一棵树,其以0为根,且$1\le i\le n ...

  8. [bzoj1385]Division expression

    容易发现a2一定是分母,且容易做到其余都是分子,因此相当于判定a2能否整除a1*a3*--*an,不断让a2除以其与其他数的gcd即可(注意特判n=1) 1 #include<bits/stdc ...

  9. C#/VB.NET 将彩色PDF转为灰度PDF

    本文以C#代码为例介绍如何实现将彩色PDF文件转为灰度(黑白)的PDF文件,即 将PDF文档里面的彩色图片或者文字等通过调用PdfGrayConverter.ToGrayPdf()方法转为文档页面为灰 ...

  10. [SQL]master..sysprocesses

    --https://docs.microsoft.com/zh-cn/sql/relational-databases/system-compatibility-views/sys-sysproces ...