博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HashMap 和 HashSet
阅读量:4693 次
发布时间:2019-06-09

本文共 2750 字,大约阅读时间需要 9 分钟。

对于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
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 }
View Code

一个重要的内部接口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
e = table[bucketIndex];4 table[bucketIndex] = new Entry
(hash,key,value,e);5 if(size++ >= threshold) //threshold包含HashMap能容纳的key-value对的极限。6 resize(2*table.length);7 }
View Code

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 HashSetTest23     {24         public static void main(String[] args)25         {26             Set
s = new HashSet
();27 s.add(new Name("abc","123"));28 System.out.println(s.contains(new Name("abc","123");29 }30 }31
View Code

运行结果是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);

  }

  ...

}

 

转载于:https://www.cnblogs.com/happinessqi/p/3440233.html

你可能感兴趣的文章
node启动时, listen EADDRINUSE 报错;
查看>>
杭电3466————DP之01背包(对状态转移方程的更新理解)
查看>>
kafka中的消费组
查看>>
python--注释
查看>>
SQL case when else
查看>>
SYS_CONTEXT 详细用法
查看>>
Pycharm配置autopep8让Python代码更符合pep8规范
查看>>
我的第一篇博客
查看>>
【C++算法与数据结构学习笔记------单链表实现多项式】
查看>>
C#垃圾回收机制
查看>>
31、任务三十一——表单联动
查看>>
python之hasattr、getattr和setattr函数
查看>>
maven使用阿里镜像配置文件
查看>>
Copy code from eclipse to word, save syntax.
查看>>
arguments.callee的作用及替换方案
查看>>
23 Java学习之RandomAccessFile
查看>>
P2709 小B的询问
查看>>
PHP echo 和 print 语句
查看>>
第一讲 一个简单的Qt程序分析
查看>>
Centos 6.5下的OPENJDK卸载和SUN的JDK安装、环境变量配置
查看>>