java性能优化读书笔记之三《程序优化===集合优化(Map)》
来源:互联网 发布:linux查看端口nc 编辑:程序博客网 时间:2024/04/30 21:26
1. 数据结构
参考博客数据结构
map概述
map的数据结构为key(键)和value(值)键值对的模式。内部原理是基于数组与单向链表的。其操作是对数组和单向链表进行增加、删除、修改、遍历。
HashMap和Hashtable不同之处在于Hashtable允许key或者value为空,再者Hashtable是线程安全的。
2. hashMap结构图(哈希表)
纵向为数组、横向为单向链表
使用场景
1、需要线程安全的,请使用Hashtable。
2、允许key或者value为空请使用Hashtable。
3、追求程序性能的,是使用HahsMap
3. HashMap源码分析
了解源码之前,请先学习一下数据结构中的哈希表以及算列法。
数组的特点是:寻址容易,插入和删除困难;而链表的特点是:寻址困难,插入和删除容易。那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表,哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法——拉链法,我们可以理解为“链表的数组。
HashMap无惨构造方法
/** * Constructs an empty <tt>HashMap</tt> with the default initial capacity * (16) and the default load factor (0.75). */ public HashMap() { //loadFactor 负载因子默认为 0.75f this.loadFactor = DEFAULT_LOAD_FACTOR; //threshold 临界值 = 默认初始容量 * 负载因子 threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); //默认初始容量(16) table = new Entry[DEFAULT_INITIAL_CAPACITY]; init(); }
从源码获取HashMap的容器容量大小为16, 扩容的临界值为12。
hashMap的put方法
* Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the old * value is replaced. * * @param key key with which the specified value is to be associated * @param value value to be associated with the specified key * @return the previous value associated with <tt>key</tt>, or * <tt>null</tt> if there was no mapping for <tt>key</tt>. * (A <tt>null</tt> return can also indicate that the map * previously associated <tt>null</tt> with <tt>key</tt>.) */ public V put(K key, V value) { //key可以为空 if (key == null) return putForNullKey(value); //取得key的hashCode int hash = hash(key.hashCode()); //取得元素在数组中的位置或者是内存中的位置 int i = indexFor(hash, table.length); //解决hash冲突,新插入的元素的数组位置如果已经被其他元素占用了,那么就使用单向链表。占用的元素链表下一个指向新插入的元素 for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } //修改记录统计 modCount++; //hash不冲突,新元素则添加到指定的数组位置 addEntry(hash, key, value, i); return null; }
根据散列法获取数组的位置
/** * Returns index for hash code h. */ static int indexFor(int h, int length) { //等同于h%length,但是不等效。h%length需要调用cpu计算。效率更低 return h & (length-1); }
HashMap数组扩容
/** * Adds a new entry with the specified key, value and hash code to * the specified bucket. It is the responsibility of this * method to resize the table if appropriate. * * Subclass overrides this to alter the behavior of put method. */ void addEntry(int hash, K key, V value, int bucketIndex) { Entry<K,V> e = table[bucketIndex]; //在指定的数组下标位置添加新元素 table[bucketIndex] = new Entry<K,V>(hash, key, value, e); //判断添加元素后的容器容量大于临界值。则需要数组扩容 if (size++ >= threshold) //扩容的容器容量= 2 * 数组长度 resize(2 * table.length); } /** * 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]; //将旧的数据内容copy扩容后新的数组 transfer(newTable); table = newTable; //重新计算临界值 = 数组长度 * 负载因子 threshold = (int)(newCapacity * loadFactor); }
4. map优化点
1、负载因子本身就是在空间和时间之间的折衷。当我使用较小的负载因子时,虽然降低了冲突的可能性,使得单个链表的长度减小了,加快了访问和更新的速度,但是它占用了更多的空间,使得数组中的大部分空间没有得到利用,元素分布比较稀疏,同时由于Map频繁的调整大小,可能会降低性能。但是如果负载因子过大,会使得元素分布比较紧凑,导致产生冲突的可能性加大,从而访问、更新速度较慢。所以我们一般推荐不更改负载因子的值,采用默认值0.75.
HashMap优化代码
暂无,后续添加
- java性能优化读书笔记之三《程序优化===集合优化(Map)》
- java性能优化读书笔记之三《程序优化===集合优化(list)》
- java性能优化读书笔记之三《程序优化===优化集合访问代码》
- java性能优化读书笔记之三《程序优化===字符串优化》
- Java程序性能优化 读书笔记(十六)集合访问优化
- 读书笔记之Java程序性能优化
- Java程序性能优化 读书笔记(九)优化组件:池
- java性能优化读书笔记之二《设计优化===单例模式》
- java性能优化读书笔记之二《设计优化===代理模式》
- java性能优化读书笔记之二《设计优化===享元模式》
- java性能优化读书笔记之二《设计优化===装饰者模式》
- java性能优化笔记(三)java程序优化
- java性能优化笔记(三)java程序优化
- java性能优化笔记(三)java程序优化
- java性能优化笔记(三)java程序优化
- JAVA性能优化权威指南 读书笔记(三)
- java 性能优化读书笔记
- 《Java性能优化...》读书笔记
- UVA 1471 Defense Lines
- Arduino - 软串口
- span标签 设置宽度
- 三个tableView的联动(省市区数组)
- apache ab.exe压力测试
- java性能优化读书笔记之三《程序优化===集合优化(Map)》
- jsp、freemarker、velocity对比
- 固定SessionID 漏洞 攻击(session fixation attacks)
- Android版添加phonegap-读取手机短信插件教程
- 给元素绑定事件时传参
- 使用Touch ID指纹解锁
- 1-1-绪论-第1章-《数据结构》课本源码-严蔚敏吴伟民版
- codeforces 416E. President's Path( graph dp)
- 文章标题