- 浏览: 276307 次
- 性别:
- 来自: 北京
最新评论
-
gotosuzhou:
好的 谢谢分享
Spring 事务异常回滚 -
cd249745647:
哈哈
Spring MVC REST 例子 -
向日葵上的小蜜蜂:
代码都差不多贴出来了,为啥不直接提供下载呢
Spring MVC REST 例子 -
he3109006290:
我猜它应该有个算法,当出现长时间处理的情况的,它自动会启动另外 ...
netty 疑惑 -
yanghoho6:
很好, 学习了,
oracle基本的索引概念.doc
今天面试提到了HasmMap,之前也有看过其源代码,了解其原理,不过又忘得差不多,今天就在读下,加深印象。
1、HashMap得内部元素以Entry存在,继承Map.Entry,元素包含,Entry相当于一个LinkedList
final Object key; Object value; final int hash; Entry next; Entry(int i, Object obj, Object obj1, Entry entry) { value = obj1; next = entry; key = obj; hash = i; }
2、HashMap得变量有
static final int DEFAULT_INITIAL_CAPACITY = 16; //默认容量 static final int MAXIMUM_CAPACITY = 1073741824; //最大容量 static final float DEFAULT_LOAD_FACTOR = 0.75F; //默认加载因子 transient Entry table[]; //HashMap得Entry集合 transient int size; //当前数量 int threshold; //容量*加载因子,当size>threshold时就会resize final float loadFactor; //加载因子 volatile transient int modCount; //修改计量,在迭代器中使用,如果迭代中有修改modCount那么会抛出ConcurrentModificationException()异常 static final Object NULL_KEY = new Object(); //默认空值 private static final boolean useNewHash = false; private transient Set entrySet;
3、put方法
public Object put(Object obj, Object obj1) { if(obj == null) return putForNullKey(obj1); //新增一个 newObjedct(),如果有null key,返回一个存在的值 //计算HashCode int i = hash(obj.hashCode()); //计算位置 相当于hashCode mod table.length 使新增的对象能平均分配到各个桶中 int j = indexFor(i, table.length); //首先根据index找到桶,然后循环桶中的Entry for(Entry entry = table[j]; entry != null; entry = entry.next) { Object obj2; //根据hashCode和(equal or ==)比较新增key是否存在,如果存在就覆盖以前的值,并返回 if(entry.hash == i && ((obj2 = entry.key) == obj || obj.equals(obj2))) { Object obj3 = entry.value; entry.value = obj1; entry.recordAccess(this); return obj3; } } modCount++; //新增entry addEntry(i, obj, obj1, j); return null; }
4、addEntry
/** * 新增一个Entry * @param i hashCode * @param obj key * @param obj1 value * @param j index,桶的位置 */ void addEntry(int i, Object obj, Object obj1, int j) { //找到桶的Entry Entry entry = table[j]; //在桶中新增一个Entry,相当于Entry.next = new Entry() table[j] = new Entry(i, obj, obj1, entry); //如果HashMap中的size大于容量*加载因子,就需要扩容,把容量*2, //从这里可以看出,HashMap希望一个Entry就一个值,尽量少的next,如果HashCode分布不均匀,那么可能数据都分配到少数桶中,使HashMap等于一个LinkedList if(size++ >= threshold) resize(2 * table.length); }
5、resize扩容
//HashMap扩容 void resize(int i) { Entry aentry[] = table; int j = aentry.length; if(j == 1073741824) { threshold = 2147483647; return; } else { //重新分配内存 Entry aentry1[] = new Entry[i]; transfer(aentry1); table = aentry1; threshold = (int)((float)i * loadFactor); return; } } void transfer(Entry aentry[]) { Entry aentry1[] = table; int i = aentry.length; //循环桶 for(int j = 0; j < aentry1.length; j++) { Entry entry = aentry1[j]; if(entry == null) continue; aentry1[j] = null; //遍历Entry,重新Hash,从这可以看出,如果可以预见HashMap的数量,那么就最好指定桶的数量,不然随着数量的增多就需要resize() //resize是非常耗性能的步骤,需要把所有的值重新resize,然后分配到各个桶中 do { Entry entry1 = entry.next; int k = indexFor(entry.hash, i); entry.next = aentry[k]; aentry[k] = entry; entry = entry1; } while(entry != null); } }
6、get方法
/** * 这个方法很简单,就是根据hashCode获取桶,然后遍历桶找key */ public Object get(Object obj) { if(obj == null) return getForNullKey(); int i = hash(obj.hashCode()); for(Entry entry = table[indexFor(i, table.length)]; entry != null; entry = entry.next) { Object obj1; if(entry.hash == i && ((obj1 = entry.key) == obj || obj.equals(obj1))) return entry.value; } return null; }
6、迭代器
/** * keyIterator,valueIterator的父类,这里都是内部类,好处是可以随意的使用外部HashMap的变量和属性 * @author Administrator * */ private abstract class HashIterator implements Iterator { /** * 构造函数,特别注意expectedModCount = modCount;这个玩意说明HashMap的Iterator是不安全的,如果在遍历过程中有修改HashMap那么就Exception了 */ HashIterator() { this$0 = HashMap.this; super(); expectedModCount = modCount; HashMap.Entry aentry[] = table; int i = aentry.length; HashMap.Entry entry = null; if(size != 0) while(i > 0 && (entry = aentry[--i]) == null) ; next = entry; index = i; } public boolean hasNext() { return next != null; } /** * * @return */ HashMap.Entry nextEntry() { if(modCount != expectedModCount) throw new ConcurrentModificationException(); HashMap.Entry entry = next; if(entry == null) throw new NoSuchElementException(); HashMap.Entry entry1 = entry.next; HashMap.Entry aentry[] = table; int i; for(i = index; entry1 == null && i > 0; entry1 = aentry[--i]); index = i; next = entry1; return current = entry; } /** * 由这个方法说明可以通过Iterator可以删除HashMap */ public void remove() { if(current == null) throw new IllegalStateException(); if(modCount != expectedModCount) { throw new ConcurrentModificationException(); } else { Object obj = current.key; current = null; removeEntryForKey(obj); expectedModCount = modCount; return; } } HashMap.Entry next; int expectedModCount; int index; HashMap.Entry current; final HashMap this$0; }
总结:
1、HashMap是根据Key的HashCode来存储和获取value的,所以Key对象最好是重载HashCode()和equals()方法,否则会导致put和get出现问题,同时也使性能出现问题
2、如果知道存储HashMap的数量,最好是指定其桶的数量,默认是16(有点小),否则会频繁的resize,每次把当前桶的数量乘以2,然后重新Hash和分配存储位置,这是个非常耗性能的过程。
3、加载因子,默认是0.75,当HashMap.size > 桶数量*加载因子时就会resize(),这个最好不要修改,保留默认值。如果过高会导致性能降低,如果过低,会浪费空间,同时会导致频繁resize()
4、HashMap是允许null的,相当于存储一个new Object();貌似意义不大
5、HashMap的迭代器是不安全的,如果在迭代器外部修改HashMap,比如add(),remove(),都会导致迭代过程中报错。
发表评论
-
自增 自减 java和c的区别
2012-03-10 15:57 1441JAVA public class Test { ... -
瞎聊系统性能优化
2012-02-19 23:46 1145一个系统中影响性能的无非就是CPU计算能力,磁盘、网络的读写能 ... -
在tomcat中,通过IP访问web系统,不需要端口号的方法(转)
2012-02-06 11:10 8885源文章地址:http://sinian.iteye.com/b ... -
java 编码
2012-02-02 18:23 1166先看一个字符串 String str = &qu ... -
javassist与classLoader
2012-02-02 15:22 4292javassist.jar是个非常 ... -
tcp 和 java socket
2011-12-31 12:52 2815tcp socket 总结点 1 ... -
netty 疑惑
2011-12-01 18:27 2703netty的nio 模式如下 一个线程Boss使用 ... -
Apache Tomcat http_proxy 连接方式配置
2011-11-02 18:03 56041、安装Tomcat ,为了使域名保持一致,在conf\Cat ... -
谈线程池
2011-10-27 12:47 1520线程池原理:用指定数 ... -
设置tomcat启动参数
2011-09-15 16:58 1524window: 在catalina.bat 文件的开始处添加如 ... -
通过反汇编class看i++和++i的区别
2011-08-17 14:32 2108public void method4() ... -
hotspot 控制参数
2011-08-17 09:25 1301文档来源于 http://www.oracle.com ... -
Spring 事务异常回滚
2011-08-16 10:10 11133先看如下代码 @Transactional ... -
java IO和NIO测试
2011-08-11 12:08 1608测试环境:cpu:Q9500 4核 频率2.83GHZ ... -
静态锁和实例锁
2011-07-28 18:21 1950Java中可以对静态方法和实例方法使用synchroni ... -
BASE64 和Dom4j
2011-07-20 09:45 1301项目当中用到MD5做消息摘要,后通过BASE64转成字符 ... -
jetty httpServer和java6内置httpServer比较
2011-07-19 12:03 3059测试情况是客户端100个线程同时同时请求10000次,服务器端 ... -
Jetty HttpClent 异常
2011-07-15 13:48 1233使用Jetty HttpClent做异步请求,结果发现这 ... -
关于Hibernate延迟加载
2011-07-14 17:42 1085package com.lottery.test; ... -
Jetty内嵌Http服务器
2011-07-14 11:13 3389本例只是以HttpServlet方式实现,更多的方式可以通过h ...
相关推荐
HashMap 是 Java 中最常用的集合类之一,它是基于哈希表实现的,提供了高效的数据存取功能。HashMap 的核心原理是将键(key)通过哈希函数转化为数组索引,然后将键值对(key-value pair)存储在数组的对应位置。...
1.面试必考之HashMap源码分析与实现 伸缩性角度看HashMap的不足
面试中,HashMap的源码分析与实现是一个常见的考察点,因为它涉及到数据结构、并发处理和性能优化等多个核心领域。本篇文章将深入探讨HashMap的内部工作原理、关键特性以及其在实际应用中的考量因素。 HashMap基于...
hashmap的原理啊思想。
#### 二、HashMap线程安全问题分析 在多线程环境中,`HashMap`的主要线程安全问题包括但不限于: 1. **链表死循环问题**:在JDK 1.7中,当多个线程同时进行`put`操作时,可能会出现链表死循环的情况,这是一个严重...
Java集合系列之HashMap源码分析 Java集合系列之HashMap源码分析是Java集合系列中的一篇非常重要的文章,它详细介绍了Java集合系列之HashMap源码,具有很高的参考价值。下面我们将对HashMap源码进行详细的分析。 ...
哈希映射(HashMap)是Java编程语言中广泛使用的数据结构之一,主要提供键值对的存储和查找功能。HashMap的实现基于哈希表的概念,它通过计算对象的哈希码来快速定位数据,从而实现了O(1)的平均时间复杂度。在深入...
微信小程序详细图文教程 泉州大白网络科技 目录 一.微信小程序申请 二....1.申请服务器 2.部署服务器 3.域名申请和配置 三....一....申请,并认证(未认证不能发布,认证需要300元,目前只支持企业认证)详细见官网说明。...
JAVA之hashmap源码分析 Mobile-Dev-Analysis Analysis of android or java 红岩网校工作站移动开发部学员分组学习 为了让大家学的更加坚固,采取小组学习的方式帮助大家学习,同时在学习研究的过程中需要不断的做...
JAVA之hashmap源码分析 无头Android堆分析器 “哈哈!” -纳尔逊 此存储库已弃用 创建该项目的目的是通过重新打包其他存储库中的堆转储解析器来提供堆转储解析器。 LeakCanary现在有它自己的。 该解析器在Maven ...
JAVA之hashmap源码分析Superword是Java开源项目,致力于研究英语单词分析和辅助阅读,包括但不限于拼写相似度,定义相似度,发音相似度,拼写转换规则,前缀和动态前缀,后缀以及动态后缀,词根,复合词,文本辅助...
四、HashMap源码分析 HashMap是一种基于散列表实现的Map,提供了快速的键值对存储和检索能力。HashMap的继承体系中,它继承了AbstractMap,实现了Map接口。 HashMap的主要属性包括键值对数组table、键值对个数size...
面试必考之HashMap源码分析与实现 ,微服务架构之Spring Cloud Eureka 场景分析与实战,高性能必学之Mysql主从架构实践 ,架构师不得不知道的Spring事物不能回滚的深层次原因 ,分库分表之后分布式下如何保证ID全局...
在本文中,我们将深入探讨如何使用Java在Android平台上实现模拟登录知乎并抓取用户信息的过程。... 首先,我们需要了解的是Android的网络访问机制。Android系统为了安全性和用户体验,对网络访问进行了限制,必须在...
《HashMap源码剖析》 HashMap是Java编程语言中一个非常重要的数据结构,它在实际开发中被广泛应用。作为集合框架的一部分,HashMap实现了Map接口,提供了高效、非同步的键值对存储功能。在这个10页的PDF文档中,...
本篇文章将通过分析一个名为"MyHashMap"的手写HashMap源码,来探讨HashMap的内部机制,帮助提升编程能力。 首先,HashMap的核心是基于哈希表的数据结构,它利用键(Key)的哈希函数将键映射到数组的特定位置,从而...