Java面试题之HashSet的实现原理

  

  

首先,我们需要知道它是组的一个实现,所以保证了当中没有重复的元素。
  一方面设置中最重要的一个操作就是查找。而且通常我们会选择

  


  

  

HashSet使用的是散列函数,那么它当中的元素也就无序可寻。当中是允许元素为零的。

  

先对实现原理进行一个总结:
  (1)基于HashMap实现的,默认构造函数是构建一个初始容量为16日负载因子为0.75的HashMap。封装了一个HashMap对象来存储所有的集合元素,所有放入HashSet中的集合元素实际上由HashMap的关键来保存,而HashMap的价值则存储了一个礼物,它是一个静态的对象对象。

  

(2)当我们试图把某个类的对象当成HashMap的键,或试图将这个类的对象放入HashSet中保存时,重写该类的=(对象obj)方法和hashCode()方法很重要,而且这两个方法的返回值必须保持一致:当该类的两个的hashCode()返回值相同时,它们通过=()方法比较也应该返回真的。通常来说,所有参与计算hashCode()返回值的关键属性,都应该用于作为=()比较的标准。

  

(3) HashSet的其他操作都是基于HashMap的。

  


  

  

它是基于HashMap实现的,HashSet底层使用HashMap来保存所有元素,因此HashSet的实现比较简单,相关HashSet的操作,基本上都是直接调用底层HashMap的相关方法来完成,HashSet的源代码如下:

        进口java.util.AbstractSet;   进口java.util.Collection;   进口java.util.HashMap;   进口java.util.LinkedHashMap;   进口java.util.Set;      进口javax.swing.text.html.HTMLDocument.Iterator;      公开课HashSet   扩展AbstractSet   可克隆,实现Set地图;//定义一个虚拟的对象对象作为HashMap的价值,将此对象定义为静态的决赛。   私有静态最终对象现在=新对象();//默认的无参构造器,构造一个空的HashSet。////实际底层会初始化一个空的HashMap,并使用默认初始容量为16和加载因子0.75。      公共HashSet () {   地图=new HashMap ();   }//构造一个包含指定中集合的元素的新设置。////实际底层使用默认的加载因子0.75和足以包含指定//集合中所有元素的初始容量来创建一个HashMap。//@param c其中的元素将存放在此组中收集的。      公共HashSet (Collection<& # 63;E>延伸;c) {   地图=new HashMap (Math.max ((int) (c.size ()/.75f) + 1, 16));   addAll (c);   }//以指定的initialCapacity负载系数和构造一个空的HashSet。////实际底层以相应的参数构造一个空的HashMap。//@param initialCapacity初始容量。//负载系数@param加载因子。      公共HashSet (int initialCapacity浮动负载系数){   地图=new HashMap (initialCapacity负载系数);   }//以指定的initialCapacity构造一个空的HashSet。////实际底层以相应的参数及加载因子负载系数为0.75构造一个空的HashMap。//@param initialCapacity初始容量。      公共HashSet (int initialCapacity) {   地图=new HashMap (initialCapacity);   }//以指定的initialCapacity负载系数和构造一个新的空链接哈希集合。//此构造函数为包访问权限,不对外公开,实际只是是对LinkedHashSet的支持。////实际底层会以指定的参数构造一个空LinkedHashMap实例来实现。//@param initialCapacity初始容量。//负载系数@param加载因子。//@param虚标记。      HashSet (int initialCapacity浮动负载系数,布尔模拟){   地图=new LinkedHashMap (initialCapacity负载系数);   }//返回对此组中元素进行迭代的迭代器。返回元素的顺序并不是特定的。////底层实际调用底层HashMap的键盘来返回所有的关键。//可见HashSet中的元素,只是存放在了底层HashMap的键上,//值使用一个静态最终的对象对象标识。//@return对此组中元素进行迭代的迭代器。      公共Iteratoriterator () {   .iterator返回map.keySet () ();      }//返回此组中的元素的数量(设置的容量)。////底层实际调用HashMap的大小()方法返回输入的数量,就得到该集合中元素的个数。//@return此组中的元素的数量(设置的容量)。      公共int大小(){   返回map.size ();   }//如果此设置不包含任何元素,则返回现实。////底层实际调用HashMap的isEmpty()判断该HashSet是否为空。//@return如果此设置不包含任何元素,则返回现实。      公共布尔isEmpty () {   返回map.isEmpty ();   }//如果此组包含指定元素,则返回现实。//更确切地讲,当且仅当此组包含一个满足(o==null & # 63;e==null: o.equals (e))//的e元素时,返回现实。////底层实际调用HashMap的containsKey判断是否包含指定键。//@param o在此组中的存在已得到测试的元素。//@return如果此组包含指定元素,则返回现实。      公共逻辑包含(对象o) {   返回map.containsKey (o);   }//如果此组中尚未包含指定元素,则添加指定元素。//更确切地讲,如果此设置没有包含满足(e==null & # 63;e2==null: e.equals (e2))//的元素e2,则向此设置添加指定的元素e。//如果此设置已包含该元素,则该调用不更改设置并返回错误的。////底层实际将将该元素作为关键放入HashMap。//由于HashMap的put()方法添加键-值对时,当新放入HashMap中关键的条目//与集合中原有条目的关键相同(hashCode()返回值相等,通过=比较也返回真正的),//新添加的条目的值会将覆盖原来输入的值,但关键不会有任何改变,//因此如果向HashSet中添加一个已经存在的元素时,新添加的集合元素将不会被放入HashMap中,//原来的元素也不会有任何改变,这也就满足了组中元素不重复的特性。//@param e将添加到此组中的元素。//@return如果此设置尚未包含指定元素,则返回现实。      公共逻辑加(E E) {   返回地图。把(e)==零;   }//如果指定元素存在于此集合中,则将其移除。//更确切地讲,如果此组包含一个满足(o==null & # 63;e==null: o.equals (e)的元素e,//则将其移除。如果此设置已包含该元素,则返回现实//(或者:如果此组因调用而发生更改,则返回真的)。(一旦调用返回,则此设置不再包含该元素)。////底层实际调用HashMap的去除方法删除指定条目。//@param o如果存在于此组中则需要将其移除的对象。//@return如果组包含指定元素,则返回现实。      公共逻辑删除对象(o) {   返回map.remove (o)==现在;   }//从此组中移除所有元素。此调用返回后,该设置将为空。////底层实际调用HashMap的明确的方法清空条目中所有元素。      公共空间clear () {   map.clear ();   }//返回此HashSet实例的浅表副本:并没有复制这些元素本身。//底层实际调用HashMap的克隆()方法,获取HashMap的浅表副本,并设置到HashSet中。      公共对象克隆(){   尝试{   HashSet

Java面试题之HashSet的实现原理