jdk1.7的HashMap重写以及与1.8的比较
如上图,HashMap是一个链表结构,获取位置下标的时候是通过hash算法来计算下标位置,同时,在存放的值超过整个容量的0.75之后会自动扩容,而且扩容之后需要重新获取entry的next指针,并且在put的时候要进行判断,这个操作是新增还是修改.
首先,定义一个MyMap接口,包含三个方法以及键值对对象:
public interface MyMap<K, V> {// 向集合中插入值public V put( K k, V v );// 根据key获取集合中的值public V get( K k );// 获得集合中元素个数public int size();// 用于获取集合中,键值对的对象interface Entry<K, V> {K getKey();V getValue();V setValue( V value );Entry<K, V> getNext();Entry<K, V> setNext( Entry<K, V> next );}
}
然后,定义MyHashMap继承上方接口,按照HashMap的实现逻辑去一步步实现:
public class MyHashMap<K, V> implements MyMap<K, V> {/*** 根据hash算法,理论上只需要查找一次就能查找到值* Entry 类型数组,默认长度16*/private Entry<K, V> table[] = null;// Hashmap的元素个数private int size;// hashmap集合中的数组的默认长度private static int defaultLength = 16;// 定义hashmap的加载银子0.75private static double defaltLoad = 0.75f;@Overridepublic V put( K k, V v ) {if ( table == null ) {table = new Entry[this.defaultLength];}if ( size >= this.defaultLength * this.defaltLoad ) {// 扩容resize();}// 1.分院,确定key/value存放吃的数组的下标位置int index = getIndex( k, this.defaultLength );// 判断是不是修改MyMap.Entry<K, V> entry = table[ index ];while( entry != null ) {if ( entry.getKey().equals( k ) ) {return entry.setValue( v );} else {entry = entry.getNext();}}// 2.创建元素,并且存放在table的index下标上table[ index ] = new Entry<>( k, v, table[ index ] );this.size++;return v;}private void resize() {// 重新散列if ( size >= this.defaultLength * this.defaltLoad ) {System.out.println( "扩容开始..." );Entry<K, V> newTable[] = new Entry[this.defaultLength << 1];MyMap.Entry<K, V> entry = null;for( int i = 0; i < table.length; i++ ) {entry = table[ i ];while( entry != null ) {int index = getIndex( entry.getKey(), newTable.length );MyMap.Entry<K, V> oldEntry = entry.getNext();entry.setNext( newTable[ index ] );newTable[ index ] = (Entry<K, V>) entry;// 继续下一个节点entry = oldEntry;}}table = newTable;this.defaultLength = newTable.length;newTable = null;}}public int getIndex( K k, int length ) {if ( k == null ) {return 0;}int hash = k.hashCode();// 与算法 & 取模return hash & ( length - 1 );}@Overridepublic V get( K k ) {if ( table != null ) {int index = getIndex( k, this.defaultLength );MyMap.Entry<K, V> entry = table[ index ];while( entry != null ) {if ( entry.getKey().equals( k ) ) {return entry.getValue();} else {entry = entry.getNext();}}}return null;}@Overridepublic int size() {return this.size;}// Entrystatic class Entry<K, V> implements MyMap.Entry<K, V> {K key;V value;MyMap.Entry<K, V> next;public Entry( K key, V value, MyMap.Entry<K, V> next ) {super();this.key = key;this.value = value;this.next = next;}@Overridepublic K getKey() {return this.key;}@Overridepublic V getValue() {// TODO Auto-generated method stubreturn this.value;}@Overridepublic V setValue( V value ) {V oldValue = this.value;this.value = value;return oldValue;}@Overridepublic MyMap.Entry<K, V> getNext() {return this.next;}@Overridepublic MyMap.Entry<K, V> setNext( MyMap.Entry<K, V> next ) {MyMap.Entry<K, V> oldNext = this.next;this.next = next;return oldNext;}}
}
最后,测试:
public class Test {public static void main( String[] args ) {MyHashMap<String, String> map = new MyHashMap<>();map.put( "1号", "打的" );map.put( "2号", "大的" );map.put( "3号", "的的" );map.put( "4号", "改动的" );map.put( "5号", "改个的" );map.put( "6号", "更大的" );map.put( "7号", "发" );map.put( "8号", "发呆" );map.put( "9号", "更大" );map.put( "10号", "更大啊" );map.put( "11号", "啊" );map.put( "12号", "个" );map.put( "13号", "人" );map.put( "14号", "让的" );map.put( "15号", "个的" );map.put( "16号", "发给谁" );map.put( "17号", "但是" );map.put( "18号", "凡事" );map.put( "19号", "给谁" );map.put( "20号", "凡事" );map.put( "21号", "胜多负少" );map.put( "22号", "发顺丰" );map.put( "23号", "凡事的" );map.put( "24号", "凡事发的" );map.put( "25号", "发呆" );map.put( "26号", "佛挡杀佛 " );map.put( "27号", "凡事的" );map.put( "28号", "凡事发多少" );map.put( "29号", "发生的的" );map.put( "30号", "凡事的" );map.put( "31号", "fsfds" );map.put( "32号", "萨芬" );System.out.println( map.get( "17号" ) );}
}
测试结果:扩容开始...
扩容开始...
但是
下面我们看看与1.8的差别:
以及数据结构的差别:
至此,我们可以看出两者之间的差别.
jdk1.7的HashMap重写以及与1.8的比较相关推荐
- jdk1.8之HashMap
转载自:http://blog.csdn.net/qq_27093465/article/details/52207135 摘要 HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数 ...
- JDK1.7和JDK1.8中HashMap是线程不安全的,并发容器ConcurrentHashMap模型
一.HashMap是线程不安全的 前言 只要是对于集合有一定了解的一定都知道HashMap是线程不安全的,我们应该使用ConcurrentHashMap.但是为什么HashMap是线程不安全的呢,之前 ...
- [Java]JDK1.7中HashMap的并发死链
[Java]JDK1.7中HashMap的并发死链 HashMap的并发死链现象发生在扩容时,在扩容过程中**transfer()**方法负责把旧的键值对转移到新的表中,其代码如下: void tra ...
- jdk1.8中HashMap扰动函数及数组长度为什么是2的n次方介绍
文章目录 前言 一.什么是二进制? 二.计算机采用二进制的原因 三.十进制与二进制相互转换 十进制转成二进制 二进制转换为十进制 与.或.异或运算 按位异或 按位与运算 按位或运算 Jdk1.8中Ha ...
- Day1、为什么JDK1.8中HashMap从头插入改成尾插入
目录 Day1.为什么JDK1.8中HashMap从头插入改成尾插入 存储方式 静态常量 插入元素 扩容 拓展问题 1.为什么JDK1.8采用红黑树存储Hash冲突的元素? 2.为什么在长度小于8时使 ...
- java hashmap hash算法,jdk1.8 中 HashMap 的 hash 算法和数组寻址
开篇 本文基于 jdk1.8 讲述 HashMap 的 hash 算法,但是不会详细介绍其他相关内容(比如用法,底层数据结构).所以必须事先知晓下面几点: HashMap 的底层数据结构是数组,在数组 ...
- 详述 JDK1.7 中 HashMap 会发生死链的原因
文章目录 前置知识 死循环执行步骤1 死循环执行步骤2 死循环执行步骤3 解决方案 总结 前置知识 HashMap死循环是一个比较常见.比较经典的问题,在日常的面试中出现的频率比较高,所以接下来咱们通 ...
- 七、JDK1.7中HashMap扩容机制
导读 前面文章一.深入理解-Java集合初篇 中我们对Java的集合体系进行一个简单的分析介绍,上两篇文章二.Jdk1.7和1.8中HashMap数据结构及源码分析 .三.JDK1.7和1.8Hash ...
- JDK1.7中HashMap底层实现原理
JDK1.7中HashMap底层实现原理 一.数据结构 HashMap中的数据结构是数组+单链表的组合,以键值对(key-value)的形式存储元素的,通过put()和get()方法储存和获取对象. ...
最新文章
- 三位数的茎叶图怎么看_霍山石斛哪家好?霍山石斛怎么选择?
- mysql 事务sqlserver_MYSQL高级特性 -- 事务处理_sqlserver
- 点击下载!《阿里云SRE技术期刊》2021年5月刊发布啦!
- leetcode 3. Longest Substring Without Repeating Characters | 3. 无重复字符的最长子串(双指针+滑窗)
- 硬核!原型和原型链详解
- linux怎样写java代码,linux 怎么写java
- 限时福利:入群锁定大会直播+PPT,听百位 AI 技术大咖、20 大热门主题分享!...
- amazon aws ip check
- 【LeetCode】【数组】题号:*498,对角线遍历
- MySQL数据库基础教程(视频)
- 20220911- LC第310场周赛
- JUCE学习笔记08-合成器(一)振荡器与包络发生器
- OpenCV IPLImage常用方法
- 用计算机弹怎么会爱上了他,怎么会爱上了他,并决定跟他回家?《纸短情长》...
- 通达信交易接口以什么形式执行下单的?
- 美赛论文Latex简易模板 | 快速上手(附注释)
- easyui ajax方式与后台servlet交互原理
- 【PS插件】Retouch4me 10合1一键安装版
- 计算机网络基础选择题
- LeetCode 344.Reverse String