- 浏览: 121211 次
- 性别:
- 来自: 杭州
-
文章分类
最新评论
-
weiwangchao:
最后一段没看明白。
深入:文本格式和二进制格式到底有什么不同? -
zbingwen:
代码下载是个二进制文档啊
python通信+多线程动手项目——多用户IM -
逸情公子:
不错不错,总结的很好,呵呵,以后面试之前就不用自己去看源码了 ...
再探集合框架(二)——深入源码看数据结构 -
zhonglou001:
您好,代码下载之后,打开为乱码??
python通信+多线程动手项目——多用户IM -
luliangy:
编程之美嘿嘿
让CPU舞动起来
如果大家看java.util.HashMap的源码的话,无非需要注意以下几点:
1、k-v如何put/get/remove
2、扩容机制
3、实际使用时,如何配置自己的table初始容量和装载因子的大小
4、如果是并发环境需要注意同步
5、key的hashcode与equals方法重写
下面,我将就这几点来谈谈我的想法:
1、k-v如何put/get/remove
首先请看懂这篇文章:http://www.iteye.com/topic/754887
上面这篇文章对put/get以及讲解的还是比较详细的,我自认为很难有新的东西讲出来,所以不赘述了。
不过,我想补充几点:
a 关于HashMap源码中的index方法:
其实如果我们去实现的时候也可以用%来做,不过有一中说法说%效率没有位运算高,我做了一个测试:
得到一组对比数据:
8-6
11-9
8-6
13-6
11-6
11-6
11-10
10-11
……
调换两个循环的顺序,测试结果:
13-7
11-13
11-11
10-12
9-8
9-8
10-10
……
我迷糊了,从上面的测试看不出什么端倪,也许从汇编的高度这个问题可以解决。我的汇编不过关,望熟悉汇编的指点一下!
b 这个算法我不是很理解
这个方法到底何用,注解了说使得哈希码的重码率降低了,我还是不明白如何能使其降低呢?难道这个方法里的算法有什么精妙之处?大家发发言
2、扩容机制
排除对一般情况下对性能影响不大的key为null和相同key值相同的情况,判断是否扩容的时机在在每put一个新元素的时候都会调用addEntry函数,这个函数中总是会判断是否需要扩容,源代码是这样的:
这里,我假设你已经看过我上面附的链接的内容并且看得八九不离十了,所以,我不再详细解释上面源码中每一个符号的意思了。我们都知道table设计为2的幂的原因是为了index函数求需要插入的新k-v对的table数组中的索引位置能用上&(当然,设计为2的倍数是否还有别的深意我还看出来)。
附上resize何transfer的源码,方便大家看:
可能在transfer方法装哦你的新老数组元素传递的时候比较难以理解,我也很难理解:put方法里新插入的元素如果出现hash collisions(哈希冲突)总是放在对应index链表的最前面的,而这里Rehashes的时候却又要在transfer方法里把链表的先后顺序给又调换过来。为什么transfer不直接写成:
3、实际使用时,如何配置自己的table初始容量和装载因子的大小
显然,按HashMap源码里的那种重构方法,如果reHash过多,显然会影响性能。所以为了防止过多的reHash,我们需要自己配置HashMap的装载因子loadFactor和初始的table容量capacity的大小(可以在构造函数里配或者调用方法配)。
很容易理解,如果我们已经知道我们使用的HashMap一般情况的存储在1W对以上,你给它一个默认的16的初始的table容量,默认reHash每次容量翻倍,这得重构多少次呀!(如果装载因子为1,还得要约5~6次)。但是如果我们的对HashMap的容量需求不是很大,你给它一个默认1W的容量,显然又浪费宝贵的空间了。至于这两个参数的选择可以自己去把握,甚至可以设定动态绑定:分析历史数据,找出规律,或者预测未来的走向找出规律。对HashMap这两个参数实现一个动态的调整。比如早上8点~9点A业务比较忙,它对应的HashMap可以提前多给些空间,而10点以后B业务使用的HashMap比较忙,A相对清闲,可以缩减A的空间给B。
4、如果是并发环境需要注意同步
显然,HashMap设计时就把它定义为不同布,或者是定义为同步工作交给程序员处理,也避免了同步带来的消耗,所以性能上还不错咯。
不过这就有些难为我们写代码的了,得自己控制呀。你得包装HashMap,不过我是不太敢用。可以尝试下java.util.concurrent包下面已经给我们做好同步的类,例如ConcurrentMap。这些类我下次大家再一起讨论吧
5、key的hashcode与equals方法重写
(这部分参考http://www.iteye.com/topic/539465中的一段然后扩展了下下)
首先,我们需要知道的是为什么需要改写key的这两方法:
正常的逻辑,这个问题可以转化为key的这两个方法在HashMap中哪里用到了(如果没用到改写干啥)。
我们ctrl+F:
put方法中第三行: int hash = hash(key.hashCode());也用到equals
putForCreate方法中第一行:int hash = (key == null) ? 0 : hash(key.hashCode());
get用到hashcode和equals
removeEntryForKey
removeMapping……
好多,不列举了。
我指针对put方法中用到的地方分析一下:
int hash = hash(key.hashCode());这一行调用了key的hashCode方法。这个方法在Object里定义,jdk中某些类有重写这个方法。其实这个方法就是哈希算法啦。这个方法的设计原则设计上就是哈希算法的设计原则了:低重码率,高性能。
在改写equals方法的时候,需要满足以下三点:
(1) 自反性:就是说a.equals(a)必须为true。
(2) 对称性:就是说a.equals(b)=true的话,b.equals(a)也必须为true。
(3) 传递性:就是说a.equals(b)=true,并且b.equals(c)=true的话,a.equals(c)也必须为true。
于是,我们可以看出所谓的key相同,包括得满足e.hash == hash && ((k = e.key) == key || key.equals(k))为true。如果你hash值相等,而我们重写的equls方法判定不为true还是算key不同的。所以,小心设计你key的这两个方法吧。
补充:
1、补充一个链接,http://java-mzd.iteye.com/blog/827523。这篇blog列举的关于index方法和解决hash collisions的方法(虽然没有细讲,只是提到)。不过,我们能了解到原来解决hash collisions 可以不仅仅事jdk里提供的挂链一种,还有很多种,还是有帮助的。这篇文章有一个简单的HashMap的实现,精神可佳,不过个人觉得没有意义不大,而且实现代码比较……
2、关于HashMap的对象持久化我还没怎么用过,如果大家用过或有经验之谈,还望交流。
b 这个算法我不是很理解
这个方法到底何用,注解了说使得哈希码的重码率降低了,我还是不明白如何能使其降低呢?难道这个方法里的算法有什么精妙之处?大家发发言
这个是和indexFor 联合起来用的,因为HashMap 的table size 都是2 的倍数,而且index = h & (length - 1),所以获得的index 的位置一般都取决于hash 的低位bits。你可以根据这个hash 算法移位看下,在低四位(也就是hashMap size 16)的情况下,这个int 里面的32bits总共有多少bits 参与了hash 运算,这就是最大可能保证了不冲突的情况
最近才看懂兄台这些话!
意思应该是:如果不经过hash()函数的运算,参与运算的位只是length-1中为1的低几位,如10110 11110 length=7的情况,只有低三位参与运算,这样两个值的index值便相同了,如果经过hash()函数就算,再调用indexfor求index,index的结果便不同。这也就是散列函数的设计目标:将key均匀和独立的分配到length长度的数组中,从而避免冲突collision的发生。
个人觉得算法和数据结构应该无关实现语言。
一时也看不出为什么用这个算法,也许经过测试这个算法误码率相对比较低并且各种情况下表现都比较好吧。
b 这个算法我不是很理解
这个方法到底何用,注解了说使得哈希码的重码率降低了,我还是不明白如何能使其降低呢?难道这个方法里的算法有什么精妙之处?大家发发言
这个是和indexFor 联合起来用的,因为HashMap 的table size 都是2 的倍数,而且index = h & (length - 1),所以获得的index 的位置一般都取决于hash 的低位bits。你可以根据这个hash 算法移位看下,在低四位(也就是hashMap size 16)的情况下,这个int 里面的32bits总共有多少bits 参与了hash 运算,这就是最大可能保证了不冲突的情况
如何自己设定扩充数量级?
下面的是我在HashMap中见到的方法, 这个方法应该可以将原来为
2^n 的容量扩充为 2^m 的容量吧? 说实话。。。没试过。。。
话说, 我们系有一个女生叫贾轶凯,名字挺像的
容量扩充的倍数在方法addEntry里面写死了:
if (size++ >= threshold)
resize(2 * table.length);
为2
被封装起来了? 没注意。。。不好意思啊
那样如果想使用估计得自己写一个子类实现了
如何自己设定扩充数量级?
下面的是我在HashMap中见到的方法, 这个方法应该可以将原来为
2^n 的容量扩充为 2^m 的容量吧? 说实话。。。没试过。。。
话说, 我们系有一个女生叫贾轶凯,名字挺像的
容量扩充的倍数在方法addEntry里面写死了:
if (size++ >= threshold)
resize(2 * table.length);
为2
没有必要自定义扩容呀,再说,写Java的人,很少关注算法,如果算法强的话,可以自行研究一套算法重新实现。
至于为什么是倍数是2,是为了防止hash 冲突。
有用的,不过很难说清楚。
比如说,一个Map里面有很多元素,如果factor设置太小的话,内部的数组体积会少开辟空间,不过开辟新数组的次说也正增多了。这个还是需要估计大小才能决定。毕竟伐值内部大小,都可以算清楚。
链表的是java.util.LinkedHashMap。
如何自己设定扩充数量级?
下面的是我在HashMap中见到的方法, 这个方法应该可以将原来为
2^n 的容量扩充为 2^m 的容量吧? 说实话。。。没试过。。。
话说, 我们系有一个女生叫贾轶凯,名字挺像的
容量扩充的倍数在方法addEntry里面写死了:
if (size++ >= threshold)
resize(2 * table.length);
为2
得到SynchronizedMap的实例,这个类作为Collection内部类。你是否选用这种方法来处理同步问题,那就看你的选择了。
如何自己设定扩充数量级?
下面的是我在HashMap中见到的方法, 这个方法应该可以将原来为
2^n 的容量扩充为 2^m 的容量吧? 说实话。。。没试过。。。
话说, 我们系有一个女生叫贾轶凯,名字挺像的
如何自己设定扩充数量级?
下面的是我在HashMap中见到的方法, 这个方法应该可以将原来为
2^n 的容量扩充为 2^m 的容量吧? 说实话。。。没试过。。。
话说, 我们系有一个女生叫贾轶凯,名字挺像的
如何自己设定扩充数量级?
赞同!
1、k-v如何put/get/remove
2、扩容机制
3、实际使用时,如何配置自己的table初始容量和装载因子的大小
4、如果是并发环境需要注意同步
5、key的hashcode与equals方法重写
下面,我将就这几点来谈谈我的想法:
1、k-v如何put/get/remove
首先请看懂这篇文章:http://www.iteye.com/topic/754887
上面这篇文章对put/get以及讲解的还是比较详细的,我自认为很难有新的东西讲出来,所以不赘述了。
不过,我想补充几点:
a 关于HashMap源码中的index方法:
/** * Returns index for hash code h. */ static int indexFor(int h, int length) { return h & (length-1); }
其实如果我们去实现的时候也可以用%来做,不过有一中说法说%效率没有位运算高,我做了一个测试:
int q=0; Long BeginTime=System.currentTimeMillis();//记录BeginTime for(int i=0;i<100000000;i++){ q=i & 10; q=i & 10; q=i & 10; q=i & 10; q=i & 10; q=i & 10; q=i & 10; q=i & 10; q=i & 10; q=i & 10; q=i & 10; q=i & 10; q=i & 10; q=i & 10; q=i & 10; q=i & 10; } Long EndTime=System.currentTimeMillis();//记录EndTime System.out.println("insert time-->"+(EndTime - BeginTime)); Long aBeginTime=System.currentTimeMillis();//记录BeginTime for(int i=0;i<100000000;i++){ q=i % 10; q=i % 10; q=i % 10; q=i % 10; q=i % 10; q=i % 10; q=i % 10; q=i % 10; q=i % 10; q=i % 10; q=i % 10; q=i % 10; q=i % 10; q=i % 10; q=i % 10; q=i % 10; } Long aEndTime=System.currentTimeMillis();//记录EndTime System.out.println("insert time-->"+(aEndTime - aBeginTime));
得到一组对比数据:
8-6
11-9
8-6
13-6
11-6
11-6
11-10
10-11
……
调换两个循环的顺序,测试结果:
13-7
11-13
11-11
10-12
9-8
9-8
10-10
……
我迷糊了,从上面的测试看不出什么端倪,也许从汇编的高度这个问题可以解决。我的汇编不过关,望熟悉汇编的指点一下!
b 这个算法我不是很理解
static int hash(int h) { // This function ensures that hashCodes that differ only by // constant multiples at each bit position have a bounded // number of collisions (approximately 8 at default load factor). h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); }
这个方法到底何用,注解了说使得哈希码的重码率降低了,我还是不明白如何能使其降低呢?难道这个方法里的算法有什么精妙之处?大家发发言
2、扩容机制
排除对一般情况下对性能影响不大的key为null和相同key值相同的情况,判断是否扩容的时机在在每put一个新元素的时候都会调用addEntry函数,这个函数中总是会判断是否需要扩容,源代码是这样的:
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) resize(2 * table.length); }
这里,我假设你已经看过我上面附的链接的内容并且看得八九不离十了,所以,我不再详细解释上面源码中每一个符号的意思了。我们都知道table设计为2的幂的原因是为了index函数求需要插入的新k-v对的table数组中的索引位置能用上&(当然,设计为2的倍数是否还有别的深意我还看出来)。
附上resize何transfer的源码,方便大家看:
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++) { Entry<K,V> e = src[j]; if (e != null) { src[j] = null; do { Entry<K,V> next = e.next; int i = indexFor(e.hash, newCapacity); e.next = newTable[i]; newTable[i] = e; e = next; } while (e != null); } } }
可能在transfer方法装哦你的新老数组元素传递的时候比较难以理解,我也很难理解:put方法里新插入的元素如果出现hash collisions(哈希冲突)总是放在对应index链表的最前面的,而这里Rehashes的时候却又要在transfer方法里把链表的先后顺序给又调换过来。为什么transfer不直接写成:
void transfer(Entry[] newTable) { Entry[] src = table; int newCapacity = newTable.length; for (int j = 0; j < src.length; j++) { Entry<K,V> e = src[j]; if (e != null) { src[j] = null; int i = indexFor(e.hash, newCapacity); newTable[i] = e;//我直接把链表挂上去 } } }
3、实际使用时,如何配置自己的table初始容量和装载因子的大小
显然,按HashMap源码里的那种重构方法,如果reHash过多,显然会影响性能。所以为了防止过多的reHash,我们需要自己配置HashMap的装载因子loadFactor和初始的table容量capacity的大小(可以在构造函数里配或者调用方法配)。
很容易理解,如果我们已经知道我们使用的HashMap一般情况的存储在1W对以上,你给它一个默认的16的初始的table容量,默认reHash每次容量翻倍,这得重构多少次呀!(如果装载因子为1,还得要约5~6次)。但是如果我们的对HashMap的容量需求不是很大,你给它一个默认1W的容量,显然又浪费宝贵的空间了。至于这两个参数的选择可以自己去把握,甚至可以设定动态绑定:分析历史数据,找出规律,或者预测未来的走向找出规律。对HashMap这两个参数实现一个动态的调整。比如早上8点~9点A业务比较忙,它对应的HashMap可以提前多给些空间,而10点以后B业务使用的HashMap比较忙,A相对清闲,可以缩减A的空间给B。
4、如果是并发环境需要注意同步
显然,HashMap设计时就把它定义为不同布,或者是定义为同步工作交给程序员处理,也避免了同步带来的消耗,所以性能上还不错咯。
不过这就有些难为我们写代码的了,得自己控制呀。你得包装HashMap,不过我是不太敢用。可以尝试下java.util.concurrent包下面已经给我们做好同步的类,例如ConcurrentMap。这些类我下次大家再一起讨论吧
5、key的hashcode与equals方法重写
(这部分参考http://www.iteye.com/topic/539465中的一段然后扩展了下下)
首先,我们需要知道的是为什么需要改写key的这两方法:
正常的逻辑,这个问题可以转化为key的这两个方法在HashMap中哪里用到了(如果没用到改写干啥)。
我们ctrl+F:
put方法中第三行: int hash = hash(key.hashCode());也用到equals
putForCreate方法中第一行:int hash = (key == null) ? 0 : hash(key.hashCode());
get用到hashcode和equals
removeEntryForKey
removeMapping……
好多,不列举了。
我指针对put方法中用到的地方分析一下:
public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); 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++; addEntry(hash, key, value, i); return null; }
int hash = hash(key.hashCode());这一行调用了key的hashCode方法。这个方法在Object里定义,jdk中某些类有重写这个方法。其实这个方法就是哈希算法啦。这个方法的设计原则设计上就是哈希算法的设计原则了:低重码率,高性能。
在改写equals方法的时候,需要满足以下三点:
(1) 自反性:就是说a.equals(a)必须为true。
(2) 对称性:就是说a.equals(b)=true的话,b.equals(a)也必须为true。
(3) 传递性:就是说a.equals(b)=true,并且b.equals(c)=true的话,a.equals(c)也必须为true。
于是,我们可以看出所谓的key相同,包括得满足e.hash == hash && ((k = e.key) == key || key.equals(k))为true。如果你hash值相等,而我们重写的equls方法判定不为true还是算key不同的。所以,小心设计你key的这两个方法吧。
补充:
1、补充一个链接,http://java-mzd.iteye.com/blog/827523。这篇blog列举的关于index方法和解决hash collisions的方法(虽然没有细讲,只是提到)。不过,我们能了解到原来解决hash collisions 可以不仅仅事jdk里提供的挂链一种,还有很多种,还是有帮助的。这篇文章有一个简单的HashMap的实现,精神可佳,不过个人觉得没有意义不大,而且实现代码比较……
2、关于HashMap的对象持久化我还没怎么用过,如果大家用过或有经验之谈,还望交流。
评论
28 楼
贾懂凯
2011-11-27
schweigen 写道
贾懂凯 写道
b 这个算法我不是很理解
static int hash(int h) { // This function ensures that hashCodes that differ only by // constant multiples at each bit position have a bounded // number of collisions (approximately 8 at default load factor). h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); }
这个方法到底何用,注解了说使得哈希码的重码率降低了,我还是不明白如何能使其降低呢?难道这个方法里的算法有什么精妙之处?大家发发言
这个是和indexFor 联合起来用的,因为HashMap 的table size 都是2 的倍数,而且index = h & (length - 1),所以获得的index 的位置一般都取决于hash 的低位bits。你可以根据这个hash 算法移位看下,在低四位(也就是hashMap size 16)的情况下,这个int 里面的32bits总共有多少bits 参与了hash 运算,这就是最大可能保证了不冲突的情况
最近才看懂兄台这些话!
意思应该是:如果不经过hash()函数的运算,参与运算的位只是length-1中为1的低几位,如10110 11110 length=7的情况,只有低三位参与运算,这样两个值的index值便相同了,如果经过hash()函数就算,再调用indexfor求index,index的结果便不同。这也就是散列函数的设计目标:将key均匀和独立的分配到length长度的数组中,从而避免冲突collision的发生。
27 楼
fjjiaboming
2011-08-09
hash()
你需要去看
The Art Of Computer Programming Vol4 的某个位置
你需要去看
The Art Of Computer Programming Vol4 的某个位置
26 楼
贾懂凯
2011-04-13
dopic 写道
看下C数据结构里面的Hash
个人觉得算法和数据结构应该无关实现语言。
25 楼
贾懂凯
2011-04-13
引用
这个是和indexFor 联合起来用的,因为HashMap 的table size 都是2 的倍数,而且index = h & (length - 1),所以获得的index 的位置一般都取决于hash 的低位bits。你可以根据这个hash 算法移位看下,在低四位(也就是hashMap size 16)的情况下,这个int 里面的32bits总共有多少bits 参与了hash 运算,这就是最大可能保证了不冲突的情况
一时也看不出为什么用这个算法,也许经过测试这个算法误码率相对比较低并且各种情况下表现都比较好吧。
24 楼
schweigen
2011-04-13
贾懂凯 写道
b 这个算法我不是很理解
static int hash(int h) { // This function ensures that hashCodes that differ only by // constant multiples at each bit position have a bounded // number of collisions (approximately 8 at default load factor). h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); }
这个方法到底何用,注解了说使得哈希码的重码率降低了,我还是不明白如何能使其降低呢?难道这个方法里的算法有什么精妙之处?大家发发言
这个是和indexFor 联合起来用的,因为HashMap 的table size 都是2 的倍数,而且index = h & (length - 1),所以获得的index 的位置一般都取决于hash 的低位bits。你可以根据这个hash 算法移位看下,在低四位(也就是hashMap size 16)的情况下,这个int 里面的32bits总共有多少bits 参与了hash 运算,这就是最大可能保证了不冲突的情况
23 楼
houzhe11
2011-04-13
要向楼主学习了。
22 楼
dopic
2011-04-13
看下C数据结构里面的Hash
21 楼
s929498110
2011-04-12
贾懂凯 写道
s929498110 写道
贾懂凯 写道
s929498110 写道
第三点
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
如何自己设定扩充数量级?
下面的是我在HashMap中见到的方法, 这个方法应该可以将原来为
2^n 的容量扩充为 2^m 的容量吧? 说实话。。。没试过。。。
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); }


容量扩充的倍数在方法addEntry里面写死了:
if (size++ >= threshold)
resize(2 * table.length);
为2
被封装起来了? 没注意。。。不好意思啊
那样如果想使用估计得自己写一个子类实现了
20 楼
mercyblitz
2011-04-12
贾懂凯 写道
s929498110 写道
贾懂凯 写道
s929498110 写道
第三点
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
如何自己设定扩充数量级?
下面的是我在HashMap中见到的方法, 这个方法应该可以将原来为
2^n 的容量扩充为 2^m 的容量吧? 说实话。。。没试过。。。
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); }


容量扩充的倍数在方法addEntry里面写死了:
if (size++ >= threshold)
resize(2 * table.length);
为2
没有必要自定义扩容呀,再说,写Java的人,很少关注算法,如果算法强的话,可以自行研究一套算法重新实现。
至于为什么是倍数是2,是为了防止hash 冲突。
19 楼
mercyblitz
2011-04-12
s929498110 写道
第三点
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
有用的,不过很难说清楚。
比如说,一个Map里面有很多元素,如果factor设置太小的话,内部的数组体积会少开辟空间,不过开辟新数组的次说也正增多了。这个还是需要估计大小才能决定。毕竟伐值内部大小,都可以算清楚。
18 楼
mercyblitz
2011-04-12
s929498110 写道
我最近也在看Collection的源码
卡在HashMap这里两天了。 对里面的hash code算法不理解,就是LZ你说的那个hash静态方法。 感觉HashMap很犀利, 即有数组的优势,也有链表的特长
卡在HashMap这里两天了。 对里面的hash code算法不理解,就是LZ你说的那个hash静态方法。 感觉HashMap很犀利, 即有数组的优势,也有链表的特长
链表的是java.util.LinkedHashMap。
17 楼
贾懂凯
2011-04-12
s929498110 写道
贾懂凯 写道
s929498110 写道
第三点
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
如何自己设定扩充数量级?
下面的是我在HashMap中见到的方法, 这个方法应该可以将原来为
2^n 的容量扩充为 2^m 的容量吧? 说实话。。。没试过。。。
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); }


容量扩充的倍数在方法addEntry里面写死了:
if (size++ >= threshold)
resize(2 * table.length);
为2
16 楼
贾懂凯
2011-04-12
s929498110 写道
第四点
文档上的说明不好用吗?
Map m = Collections.synchronizedMap(new HashMap(...));
这样的一个HashMap线程不安全? 表示完全没试过。。。仅存理论啊
文档上的说明不好用吗?
Map m = Collections.synchronizedMap(new HashMap(...));
这样的一个HashMap线程不安全? 表示完全没试过。。。仅存理论啊
得到SynchronizedMap的实例,这个类作为Collection内部类。你是否选用这种方法来处理同步问题,那就看你的选择了。
15 楼
s929498110
2011-04-12
晕。。。 网络一卡
放了两遍。。。
零点了, 睡觉! 明天还得早起去实验室干活呢!
放了两遍。。。
零点了, 睡觉! 明天还得早起去实验室干活呢!
14 楼
s929498110
2011-04-11
贾懂凯 写道
s929498110 写道
第三点
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
如何自己设定扩充数量级?
下面的是我在HashMap中见到的方法, 这个方法应该可以将原来为
2^n 的容量扩充为 2^m 的容量吧? 说实话。。。没试过。。。
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); }


13 楼
s929498110
2011-04-11
贾懂凯 写道
s929498110 写道
第三点
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
如何自己设定扩充数量级?
下面的是我在HashMap中见到的方法, 这个方法应该可以将原来为
2^n 的容量扩充为 2^m 的容量吧? 说实话。。。没试过。。。
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); }


12 楼
贾懂凯
2011-04-11
s929498110 写道
第三点
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
如何自己设定扩充数量级?
11 楼
贾懂凯
2011-04-11
s929498110 写道
LZ
HashMap容器重新装载的方法, 你修改的不正确
比如第一个key的哈希值是1234
第二个key的哈希值是12345
可能旧的容器的 table.length比较小, indexOf返回的值是一样的
而新的容器的table.length比较大, indexOf的返回值可能不一样!
也就是容器扩充之后, 原来挂载点相同的Entry,新的挂载点可能不同
你感觉我说的对不?
HashMap容器重新装载的方法, 你修改的不正确
比如第一个key的哈希值是1234
第二个key的哈希值是12345
可能旧的容器的 table.length比较小, indexOf返回的值是一样的
而新的容器的table.length比较大, indexOf的返回值可能不一样!
也就是容器扩充之后, 原来挂载点相同的Entry,新的挂载点可能不同
你感觉我说的对不?
赞同!
10 楼
s929498110
2011-04-11
第四点
文档上的说明不好用吗?
Map m = Collections.synchronizedMap(new HashMap(...));
这样的一个HashMap线程不安全? 表示完全没试过。。。仅存理论啊
文档上的说明不好用吗?
Map m = Collections.synchronizedMap(new HashMap(...));
这样的一个HashMap线程不安全? 表示完全没试过。。。仅存理论啊
9 楼
s929498110
2011-04-11
第三点
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
我感觉装载因子好像不推荐修改吧? 如果一次性容量扩充比较大的话
可以自己设定扩充倍数数量级的
但是说实话。装载因子的使用经验几乎为零。。。现在读大二,实战经验也没多少。就不发表意见了。。。
发表评论
-
并发容器——BlockingQueue相关类
2011-04-20 13:23 3223java.util.concurrent提供了 ... -
简单比较HashMap和Hashtable
2011-04-17 23:47 1573Hashtable作为遗留类,其实完全可以弃置不用了。从这个角 ... -
引用类,WeakHashMap,以及让value自动回收
2011-04-13 19:32 2384如果要彻底明白WeakHashMap这个类,需要联系GC ... -
集合框架(三)-专用set和map机制分析
2010-11-28 13:05 1255------------------------------- ... -
再探集合框架(二)——深入源码看数据结构
2010-11-26 16:58 3576这篇我准备从源码的高度来看看集合中各个实现类的是如何组织我们存 ... -
从提高存取效率的角度深入“集合框架”
2010-10-19 17:08 1384在开始之前,我先提出问题引出整片的论述: ...
相关推荐
查看进程信息,方便排查问题
IDA Pro分析STM32F1xx插件
项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用
小型的微电网仿真模型,简单模拟了光伏,家庭负载变化的使用情况
MATLAB代码实现:分布式电源接入对配电网运行影响深度分析与评估,MATLAB代码分析:分布式电源接入对配电网运行影响评估,MATLAB代码:分布式电源接入对配电网影响分析 关键词:分布式电源 配电网 评估 参考文档:《自写文档,联系我看》参考选址定容模型部分; 仿真平台:MATLAB 主要内容:代码主要做的是分布式电源接入场景下对配电网运行影响的分析,其中,可以自己设置分布式电源接入配电网的位置,接入配电网的有功功率以及无功功率的大小,通过牛顿拉夫逊法求解分布式电源接入后的电网潮流,从而评价分布式电源接入前后的电压、线路潮流等参数是否发生变化,评估配电网的运行方式。 代码非常精品,是研究含分布式电源接入的电网潮流计算的必备程序 ,分布式电源; 配电网; 接入影响分析; 潮流计算; 牛顿拉夫逊法; 电压评估; 必备程序。,基于MATLAB的分布式电源对配电网影响评估系统
项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用
重庆市农村信用合作社 农商行数字银行系统建设方案.ppt
光伏并网逆变器设计方案与高效实现:结合matlab电路仿真、DSP代码及环流抑制策略,光伏并网逆变器设计方案:结合matlab电路文件与DSP程序代码,实现高效并联环流抑制策略,光伏并网逆变器设计方案,附有相关的matlab电路文件,以及DSP的程序代码,方案、仿真文件、代码三者结合使用效果好,事半功倍。 备注:赠送逆变器并联环流matlab文件,基于矢量控制的环流抑制策略和下垂控制的环流抑制 ,光伏并网逆变器设计方案; MATLAB电路文件; DSP程序代码; 方案、仿真文件、代码结合使用; 并联环流抑制策略; 下垂控制的环流抑制,光伏并网逆变器优化设计:方案、仿真与DSP程序代码三合一,并赠送并联环流抑制策略Matlab文件
内容概要:本文介绍了通过 Matlab 实现鲸鱼优化算法(WOA)与门控循环单元(GRU)结合的多输入分类预测模型。文章首先概述了时间序列预测的传统方法局限性以及引入 WOA 的优势。然后,重点阐述了项目背景、目标、挑战及其独特之处。通过详细介绍数据预处理、模型构建、训练和评估步骤,最终展示了模型的效果预测图及应用实例。特别强调利用 WOA 改善 GRU 的参数设置,提高了多输入时间序列预测的准确性与鲁棒性。 适合人群:对时间序列分析有兴趣的研究者,从事金融、能源、制造业等行业数据分析的专业人士,具备一定的机器学习基础知识和技术经验。 使用场景及目标:本项目旨在开发一个高度准确和稳定的多变量时间序列预测工具,能够用于金融市场预测、能源需求规划、生产调度优化等领域,为企业和个人提供科学决策依据。 其他说明:项目提供的源代码和详细的开发指南有助于学习者快速掌握相关技能,并可根据实际需求调整模型参数以适应不同的业务情境。
项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用
内容概要:本文介绍了Python中基于双向长短期记忆网络(BiLSTM)与AdaBoost相结合的多输入分类预测模型的设计与实现。BiLSTM擅长捕捉时间序列的双向依赖关系,而AdaBoost则通过集成弱学习器来提高分类精度和稳定性。文章详述了该项目的背景、目标、挑战、特色和应用场景,并提供了详细的模型构建流程、超参数优化以及视觉展示的方法和技术要点。此外,还附有完整的效果预测图表程序和具体示例代码,使读者可以快速上手构建属于自己的高效稳定的时间序列预测系统。 适合人群:对深度学习特别是时序数据分析感兴趣的开发者或者科研工作者;正在探索高级机器学习技术和寻求解决方案的企业分析师。 使用场景及目标:适用于希望提升时间序列或多输入数据类别判定准确度的业务情境,比如金融市场的走势预估、医学图像分析中的病变区域判读或是物联网环境监测下设备状态预警等任务。目的是为了创建更加智能且可靠的预测工具,在实际应用中带来更精准可靠的结果。 其他说明:文中提供的所有Python代码片段和方法都可以直接运用于实践中,并可根据特定的问题进行相应调整和扩展,进一步改进现有系统的效能并拓展新的功能特性。
1、文件内容:maven-script-interpreter-javadoc-1.0-7.el7.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/maven-script-interpreter-javadoc-1.0-7.el7.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
在云服务器上搭建MQTT服务器(超详细,一步到位)
复现改进的L-SHADE差分进化算法求解最优化问题详解:附MATLAB源码与测试函数集,复现改进的L-SHADE差分进化算法求解最优化问题详解:MATLAB源码与测试集全攻略,复现改进的L-SHADE差分进化算法求最优化问题 对配套文献所提出的改进的L-SHADE差分进化算法求解最优化问题的的复现,提供完整MATLAB源代码和测试函数集,到手可运行,运行效果如图2所示。 代码所用测试函数集与文献相同:对CEC2014最优化测试函数集中的全部30个函数进行了测试验证,运行结果与文献一致。 ,复现; 改进的L-SHADE差分进化算法; 最优化问题求解; MATLAB源代码; 测试函数集; CEC2014最优化测试函数集,复现改进L-SHADE算法:最优化问题的MATLAB求解与验证
天津大学:深度解读DeepSeek原理与效应.pdf 1.大语言模型发展路线图 2.DeepSeek V2-V3/R1技术原理 3DeepSeek效应 4.未来展望
光伏混合储能微电网能量管理系统模型:基于MPPT控制的光伏发电与一阶低通滤波算法的混合储能系统优化管理,光伏混合储能微电网能量优化管理与稳定运行系统,光伏-混合储能微电网能量管理系统模型 系统主要由光伏发电模块、mppt控制模块、混合储能系统模块、直流负载模块、soc限值管理控制模块、hess能量管理控制模块。 光伏发电系统采用mppt最大跟踪控制,实现光伏功率的稳定输出;混合储能系统由蓄电池和超级电容组合构成,并采用一阶低通滤波算法实现两种储能介质间的功率分配,其中蓄电池响应目标功率中的低频部分,超级电容响应目标功率中的高频部分,最终实现对目标功率的跟踪响应;SOC限值管理控制,根据储能介质的不同特性,优化混合储能功率分配,进一步优化蓄电池充放电过程,再根据超级电容容量特点,设计其荷电状态区分管理策略,避免过充过放,维持系统稳定运行;最后,综合混合储能和系统功率平衡,针对光伏储能微电网的不同工况进行仿真实验,验证控制策略的有效性。 本模型完整无错,附带对应复现文献paper,容易理解,可塑性高 ,光伏; 混合储能系统; 能量管理; MPPT控制; 直流负载;
Matlab算法下的A星路径规划改进版:提升搜索效率,优化拐角并路径平滑处理,Matlab下的A星算法改进:提升搜索效率、冗余拐角优化及路径平滑处理,Matlab算法代码 A星算法 路径规划A* Astar算法仿真 传统A*+改进后的A*算法 Matlab代码 改进: ①提升搜索效率(引入权重系数) ②冗余拐角优化(可显示拐角优化次数) ③路径平滑处理(引入梯度下降算法配合S-G滤波器) ,Matlab算法代码; A星算法; 路径规划A*; Astar算法仿真; 传统A*; 改进A*算法; 提升搜索效率; 冗余拐角优化; 路径平滑处理; 权重系数; S-G滤波器。,Matlab中的A*算法:传统与改进的路径规划仿真研究
项目开发所用的主要提示词模板
项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行;功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用
电力系统暂态稳定性仿真分析:Matlab编程与Simulink模型下的各类故障影响研究,电力系统暂态稳定性仿真分析:Matlab编程与Simulink模型下的各类故障影响研究,电力系统暂态稳定性Matlab编程 Simulink仿真 单机无穷大系统发生各类(三相短路,单相接地,两相接地,两相相间短路)等短路故障,各类(单相断线,两相断线,三相断线)等断线故障,暂态稳定仿真分析 Simulink搭建电力系统暂态仿真模型 通过仿真,观察串联电抗器,并联补偿器,自动重合闸,以及故障切除快慢对暂态稳定性的影响 ,电力系统暂态稳定性; Matlab编程; Simulink仿真; 短路故障; 断线故障; 暂态稳定仿真分析; 仿真模型搭建; 电抗器影响; 补偿器影响; 自动重合闸; 故障切除时间。,Matlab编程与Simulink仿真在电力系统暂态稳定性分析中的应用