HashTable-HashMap(Android,Java最常见面试题)

来源:互联网 发布:考研大数据 编辑:程序博客网 时间:2024/06/03 20:17

摘要:作为毕业党的一员,最近一直处于笔试面试的状态中,这么多笔试面试中,HashTable和HashMap是最常见的一个面试题,为了避免在一个坑上掉下去两次,准备好好进行整理和研究下。

HashMap

概述

实现接口:Serializable, Cloneable, Map< K,V >
继承:AbstractMap< K,V >
HashMap是一种基于哈希表(hash table)实现的map,哈希表(也叫关联数组)一种通用的数据结构,大多数的现代语言都原生支持,其概念也比较简单:key经过hash函数作用后得到一个槽(buckets或slots)的索引(index),槽中保存着我们想要获取的值,如下图所示这里写图片描述

特点

  1. 线程非安全,并且允许key与value都为null值,HashTable与之相反,为线程安全,key与value都不允许null值。
  2. 不保证其内部元素的顺序,而且随着时间的推移,同一元素的位置也可能改变(resize的情况)
  3. put、get操作的时间复杂度为O(1),constant-time performance for the basic operations (get and put)
  4. 遍历其集合性能的时间复杂度与其容量(capacity,槽的个数)和现有元素的大小(entry的个数)成正比,所以如果遍历的性能要求很高,不要把capactiy设置的过高或把平衡因子(load factor,当entry数大于capacity*loadFactor时,会进行resize,reside会导致key进行rehash)设置的过低。
  5. 由于HashMap是线程非安全的,这也就是意味着如果多个线程同时对一hashmap的集合试图做迭代时有结构的上改变(添加、删除entry,只改变entry的value的值不算结构改变),那么会报ConcurrentModificationException,专业术语叫fail-fast,尽早报错对于多线程程序来说是很有必要的。(官方解决方案:Map m = Collections.synchronizedMap(new HashMap(…));)

构造函数与哈希算法

可参考源码与下面这个博客,该篇博客讲解了源码和哈希函数,讲的比较详细,大家可以对照源码进行理解。以及如何解决哈希值冲突。
http://liujiacai.net/blog/2015/09/03/java-hashmap/

哈希冲突解决办法

开放地址法

当冲突发生时,使用某种探查(亦称探测)技术在散列表中形成一个探查(测)序列。沿此序列逐个单元地查找,直到找到给定 的关键字,或者碰到一个开放的地址(即该地址单元为空)为止(若要插入,在探查到开放的地址,则可将待插入的新结点存人该地址单元)。查找时探查到开放的 地址则表明表中无待查的关键字,即查找失败。

拉链法

拉链法解决冲突的做法是:将所有关键字为同义词的结点链接在同一个单链表中。若选定的散列表长度为m,则可将散列表定义为一个由m个头指针组成的指针数 组T[0..m-1]。凡是散列地址为i的结点,均插入到以T[i]为头指针的单链表中。T中各分量的初值均应为空指针。在拉链法中,装填因子α可以大于 1,但一般均取α≤1。

再哈希

构造多个哈希函数,直到不产生冲突,当然这对性能的损耗很大。

HashTable

概述

实现接口:Serializable, Cloneable, Map< K,V >
继承:Dictionary< K,V >
HashMap是一种基于哈希表(hash table)实现的map,哈希表(也叫关联数组)一种通用的数据结构,大多数的现代语言都原生支持,其概念也比较简单:key经过hash函数作用后得到一个槽(buckets或slots)的索引(index),槽中保存着我们想要获取的值,如下图所示

特点

  1. key与value都不允许null值。(Any non-null object can be used as a key or as a value.)
  2. 作为key的对象必须实现hashcode()和equals()方法
  3. 线程安全的,其他特点同HashMap

构造函数与哈希算法

HashTable采用”拉链法”实现哈希表,它定义了几个重要的参数:table、count、threshold、loadFactor、modCount。
主要的构造方法参考源码或者以下博客:
http://cmsblogs.com/?p=618

两者区别

  1. 是否允许null值和null key
  2. 是否线程安全
  3. 继承的父类不同
  4. 遍历方式不同,hashtable使用了Enumeration
  5. 哈希值不同,hashtable直接使用对象hashcode,而hashmap重写
  6. hashtable中数组默认大小为11,增加方式为old*2+1;hashmap中数组默认大小为16,而且一定是2的指数。

参考

HashMap
http://liujiacai.net/blog/2015/09/01/java-collection-overview/
http://liujiacai.net/blog/2015/09/03/java-hashmap/
http://www.360doc.com/content/14/0721/09/16319846_395862328.shtml
http://blog.csdn.net/willfcareer/article/details/6687117
HashTable
http://cmsblogs.com/?p=618
http://perhaps.cnblogs.com/archive/2006/01/06/312335.html
http://blog.csdn.net/chenssy/article/details/22896871
http://www.cnblogs.com/yangleiWPF/archive/2010/11/16/1878494.html

0 0