当前位置: 首页 > news >正文

网站建设+荆州重庆沙坪坝有什么好玩的

网站建设+荆州,重庆沙坪坝有什么好玩的,青岛高端网站开发公司,wordpress云主机模板1 HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储#xff0c;但这两者基本上是两个极端。 数组 数组存储区间是连续的#xff0c;占用内存严重#xff0c;故空间复杂的很大。但数组的二分查找时间复杂度小#xff0c;为O(1)#xff1b;数组的特点是#xf…1 HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储但这两者基本上是两个极端。 数组 数组存储区间是连续的占用内存严重故空间复杂的很大。但数组的二分查找时间复杂度小为O(1)数组的特点是寻址容易插入和删除困难 链表 链表存储区间离散占用内存比较宽松故空间复杂度很小但时间复杂度很大达ON。链表的特点是寻址困难插入和删除容易。 哈希表 那么我们能不能综合两者的特性做出一种寻址容易插入删除也容易的数据结构答案是肯定的这就是我们要提起的哈希表。哈希表(Hash table既满足了数据的查找方便同时不占用太多的内容空间使用也十分方便。   从上图我们可以发现哈希表是由数组链表组成的一个长度为16的数组中每个元素存储的是一个链表的头结点。那么这些元素是按照什么样的规则存储到数组中呢。一般情况是通过hash(key)%len获得也就是元素的key的哈希值对数组长度取模得到。比如上述哈希表中12%1612,28%1612,108%1612,140%1612。所以12、28、108以及140都存储在数组下标为12的位置。   HashMap其实也是一个线性的数组实现的,所以可以理解为其存储数据的容器就是一个线性数组。这可能让我们很不解一个线性的数组怎么实现按键值对来存取数据呢这里HashMap有做一些处理。   首先HashMap里面实现一个静态内部类Entry其重要的属性有 key , value, next从属性key,value我们就能很明显的看出来Entry就是HashMap键值对实现的一个基础bean我们上面说到HashMap的基础就是一个线性数组这个数组就是Entry[]Map里面的内容都保存在Entry[]里面。     /**      * The table, resized as necessary. Length MUST Always be a power of two.      */     transient Entry[] table;     2. HashMap的存取实现        既然是线性数组为什么能随机存取这里HashMap用了一个小算法大致是这样实现 1 // 存储时: 2 int hash key.hashCode(); // 这个hashCode方法这里不详述,只要理解每个key的hash是一个固定的int值 3 int index hash % Entry[].length; 4 Entry[index] value; 5 6 // 取值时: 7 int hash key.hashCode(); 8 int index hash % Entry[].length; 9 return Entry[index]; 1put 疑问如果两个key通过hash%Entry[].length得到的index相同会不会有覆盖的危险   这里HashMap里面用到链式数据结构的一个概念。上面我们提到过Entry类里面有一个next属性作用是指向下一个Entry。打个比方 第一个键值对A进来通过计算其key的hash得到的index0记做:Entry[0] A。一会后又进来一个键值对B通过计算其index也等于0现在怎么办HashMap会这样做:B.next A,Entry[0] B,如果又进来C,index也等于0,那么C.next B,Entry[0] C这样我们发现index0的地方其实存取了A,B,C三个键值对,他们通过next这个属性链接在一起。所以疑问不用担心。也就是说数组中存储的是最后插入的元素。到这里为止HashMap的大致实现我们应该已经清楚了。    public V put(K key, V value) {         if (key  null)             return putForNullKey(value); //null总是放在数组的第一个链表中         int hash  hash(key.hashCode());         int i  indexFor(hash, table.length);         //遍历链表         for (EntryK,V e  table[i]; e ! null; e  e.next) {             Object k;             //如果key在链表中已存在则替换为新value             if (e.hash  hash  ((k  e.key)  key || key.equals(k))) {                 V oldValue  e.value;                 e.value  value;                 e.recordAccess(this);                 return oldValue;             }         }         modCount;         addEntry(hash, key, value, i);         return null;     }   void addEntry(int hash, K key, V value, int bucketIndex) {     EntryK,V e  table[bucketIndex];     table[bucketIndex]  new EntryK,V(hash, key, value, e); //参数e, 是Entry.next     //如果size超过threshold则扩充table大小。再散列     if (size  threshold)             resize(2 * table.length); }   当然HashMap里面也包含一些优化方面的实现这里也说一下。比如Entry[]的长度一定后随着map里面数据的越来越长这样同一个index的链就会很长会不会影响性能HashMap里面设置一个因子随着map的size越来越大Entry[]会以一定的规则加长长度。   2get  public V get(Object key) {         if (key  null)             return getForNullKey();         int hash  hash(key.hashCode());         //先定位到数组元素再遍历该元素处的链表         for (EntryK,V e  table[indexFor(hash, table.length)];              e ! null;              e  e.next) {             Object k;             if (e.hash  hash  ((k  e.key)  key || key.equals(k)))                 return e.value;         }         return null; }   3null key的存取 null key总是存放在Entry[]数组的第一个元素。    private V putForNullKey(V value) {         for (EntryK,V e  table[0]; e ! null; e  e.next) {             if (e.key  null) {                 V oldValue  e.value;                 e.value  value;                 e.recordAccess(this);                 return oldValue;             }         }         modCount;         addEntry(0, null, value, 0);         return null;     }     private V getForNullKey() {         for (EntryK,V e  table[0]; e ! null; e  e.next) {             if (e.key  null)                 return e.value;         }         return null;     }     4确定数组indexhashcode % table.length取模 HashMap存取时都需要计算当前key应该对应Entry[]数组哪个元素即计算数组下标算法如下    /**      * Returns index for hash code h.      */     static int indexFor(int h, int length) {         return h  (length-1);     } 按位取并作用上相当于取模mod或者取余%。 这意味着数组下标相同并不表示hashCode相同。   5table初始大小     public HashMap(int initialCapacity, float loadFactor) {         .....        // Find a power of 2  initialCapacity         int capacity  1;         while (capacity  initialCapacity)             capacity  1;         this.loadFactor  loadFactor;         threshold  (int)(capacity * loadFactor);         table  new Entry[capacity];         init();     }   注意table初始大小并不是构造函数中的initialCapacity 而是 initialCapacity的2的n次幂 ————为什么这么设计呢—— 3. 解决hash冲突的办法 开放定址法线性探测再散列二次探测再散列伪随机探测再散列再哈希法链地址法建立一个公共溢出区Java中hashmap的解决办法就是采用的链地址法。   4. 再散列rehash过程 当哈希表的容量超过默认容量时必须调整table的大小。当容量已经达到最大可能值时那么该方法就将容量调整到Integer.MAX_VALUE返回这时需要创建一张新表将原表的映射到新表中。    /**      * Rehashes the contents of this map into a new array with a      * larger capacity.  This method is called automatically when the      * number of keys in this map reaches its threshold.      *      * If current capacity is MAXIMUM_CAPACITY, this method does not      * resize the map, but sets threshold to Integer.MAX_VALUE.      * This has the effect of preventing future calls.      *      * param newCapacity the new capacity, MUST be a power of two;      *        must be greater than current capacity unless current      *        capacity is MAXIMUM_CAPACITY (in which case value      *        is irrelevant).      */     void resize(int newCapacity) {         Entry[] oldTable  table;         int oldCapacity  oldTable.length;         if (oldCapacity  MAXIMUM_CAPACITY) {             threshold  Integer.MAX_VALUE;             return;         }         Entry[] newTable  new Entry[newCapacity];         transfer(newTable);         table  newTable;         threshold  (int)(newCapacity * loadFactor);     }       /**      * Transfers all entries from current table to newTable.      */     void transfer(Entry[] newTable) {         Entry[] src  table;         int newCapacity  newTable.length;         for (int j  0; j  src.length; j) {             EntryK,V e  src[j];             if (e ! null) {                 src[j]  null;                 do {                     EntryK,V next  e.next;                     //重新计算index                     int i  indexFor(e.hash, newCapacity);                     e.next  newTable[i];                     newTable[i]  e;                     e  next;                 } while (e ! null);             }         }       } 转载于:https://www.cnblogs.com/betterboyz/p/8556954.html
http://www.zqtcl.cn/news/281221/

相关文章:

  • 电子商务网站建设财务分析建立网站方法
  • 大专学网站开发wordpress显示数据库请求
  • 诸暨网站制作设计公众号文章怎么导入到wordpress
  • 网站死链怎么办青岛网站制作企业
  • 已经有域名 怎么修改网站网站推广找客户
  • 网站的制作建站人增加网站流量
  • 向国旗致敬做时代新人网站广州网站建设公司排名
  • 阿里云域名怎么做网站对网站进行seo优化
  • 响应式网站建设合同11月将现新冠感染高峰
  • 做网站客户一般会问什么问题百度云网盘资源分享网站
  • 网站设计中超链接怎么做艺术设计
  • 卡盟网站建设wordpress优化代码
  • 做网站需要什么技术员商城型网站开发网站建设
  • discuz做地方门户网站网站大全免费完整版
  • 莆田人做的网站一天赚2000加微信
  • 阿里云网站访问不了怎么办做网站二维码
  • 手机商城网站建设可采用的基本方式有
  • 网站备案管理做广告公司网站建设价格
  • 绵阳专业网站建设公司上海外贸公司排名榜
  • 如何做英文系统下载网站快速排名工具免费
  • 苏州建网站必去苏州聚尚网络网页视频提取在线工具
  • 网站建设服务市场分析百度集团
  • 网站怎么企业备案信息做网站业务员如何跟客户沟通
  • 如何网站推广知名的集团门户网站建设费用
  • 网站入口设计规范专门做喷涂设备的网站
  • 最简单网站开发软件有哪些企业管理培训课程培训机构
  • 桂城网站制作公司wordpress 导航网站
  • 一个公司做网站需要注意什么条件网站备案 登陆
  • 百度网站介绍显示图片装修公司一般多少钱一平方
  • 网站销售如何做业绩我找伟宏篷布我做的事ko家的网站