自己动手实现java数据结构(五)哈希表(4)
2. 当迭代器的下标到达当前插槽链表的末尾时,迭代器下标需要跳转到靠后插槽的第一个非空数据节点。 * 哈希表 迭代器实现 class Itr implements Iterator<EntryNode<K,1)"> { * 迭代器 当前节点 * */ currentNode; * 迭代器 下一个节点 * nextNode; * 迭代器 当前内部数组的下标 * currentIndex; * 默认构造方法 * private Itr(){ :::如果当前哈希表为空,直接返回 if(HashMap..isEmpty()){ ; } :::在构造方法中,将迭代器下标移动到第一个有效的节点上 :::遍历内部数组,找到第一个不为空的数组插槽slot int i=0; i<HashMap.:::设置当前index this.currentIndex = i; EntryNode<K,V> firstEntryNode = HashMap..elements[i]; :::找到了第一个不为空的插槽slot if(firstEntryNode != :::nextNode = 当前插槽第一个节点 this.nextNode = firstEntryNode; :::构造方法立即结束 ; } } } @Override hasNext() { this.nextNode != ); } @Override public EntryNode<K,1)"> next() { this.currentNode = .nextNode; :::暂存需要返回的节点 EntryNode<K,V> needReturn = .nextNode; :::nextNode指向自己的next this.nextNode = .nextNode.next; :::判断当前nextNode是否为null this.nextNode == :::说明当前所在的桶链表已经遍历完毕 :::寻找下一个非空的插槽 int i=this.currentIndex+1; i<HashMap.:::设置当前index i; EntryNode<K,1)">.elements[i]; :::找到了后续不为空的插槽slot ){ :::nextNode = 当前插槽第一个节点 firstEntryNode; :::跳出循环 break; } } } needReturn; } @Override remove() { this.currentNode == throw new IteratorStateErrorException("迭代器状态异常: 可能在一次迭代中进行了多次remove操作"); } :::获得需要被移除的节点的key K currentKey = .currentNode.key; :::将其从哈希表中移除 HashMap..remove(currentKey); :::currentNode设置为null,防止反复调用remove方法 ; } } 5.哈希表性能5.1 空间效率:哈希表的空间效率很大程度上取决于负载因子。通常,为了保证哈希表查询的高效性,负载因子都设置的比较小(小于1),因而可能会出现许多空的插槽,浪费空间。 总体而言,哈希表的空间效率低于向量和链表。 5.2 时间效率:一般的,哈希表增删改查接口的时间复杂度都是O(1)。但是出现较多的hash冲突时,冲突范围内的key的增删改查效率较低,时间效率会有一定的波动。 总体而言,哈希表的时间效率高于向量和链表。 哈希表的时间效率很高,可天下没有免费的午餐,据统计,哈希表的空间利用率通常情况下还不到50%。 哈希表是一个使用空间来换取时间的数据结构,对查询性能有较高要求的场合,可以考虑使用哈希表。 6.哈希表总结6.1 当前版本缺陷至此,我们已经实现了一个基础的哈希表,但还存在许多明显缺陷: 1.当hash冲突比较频繁时,查询效率急剧降低。 jdk在1.8版本的哈希表实现(java.util.HashMap)中,对这一场景进行了优化。当内部桶链表的节点个数超过一定数量(默认为8)时,会将插槽中的桶链表转换成一个红黑树(查询效率为O(logN))。 2.不支持多线程 在多线程的环境,并发的访问一个哈希表会导致诸如:扩容时内部节点死循环、丢失插入数据等异常情况。 6.2 查询特定元素的方法我们目前查询特定元素有几种不同的方法: 1.顺序查找 在无序向量或者链表中,查找一个特定元素是通过从头到尾遍历容器内元素的方式实现的,执行速度正比于数据量的大小,顺序查找的时间复杂度为O(n),效率较低。 2.二分查找 在有序向量以及后面要介绍的二叉搜索树中,由于容器内部的元素是有序的,因此可以通过二分查找比较的方式查询特定的元素,二分查找的时间复杂度为O(logN),效率较高。 3.哈希查找 在哈希表中,通过直接计算出数据hash值对应的插槽(slot)(时间复杂度O(1)),查找出对应的数据,哈希查找的时间复杂度为O(1),效率极高。 特定元素的查找方式和排序算法的关系 1.顺序查找对应冒泡排序、选择排序等,效率较低,时间复杂度(O(n2))。 2.二分查找对应快速排序、归并排序等,效率较高,时间复杂度(O(nLogn))。 3.哈希查找对应基排序,效率极高,时间复杂度(O(n))。 在大牛刘未鹏的博客中有更为详细的说明,http://mindhacks.cn/2008/06/13/why-is-quicksort-so-quick。 6.3 完整代码(编辑:ASP站长网) |