- 浏览: 236898 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
nujgnef:
[size=x-large][color=yellow][/c ...
Spring中PROPAGATION_REQUIRED的意思? -
wrq_mimi:
...
使用BeanNameAutoProxyCreator实现spring的自动代理 -
Luob.:
不行啊 ,我这里报错了org.springframework. ...
使用BeanNameAutoProxyCreator实现spring的自动代理 -
blueman2012:
附件在哪儿呢,亲亲
Ehcache缓存框架 -
zskangs1126:
mysql 基本语句
Hashtable和HashMap类有三个重要的不同之处。第一个不同主要是历史原因。Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现。
也许最重要的不同是Hashtable的方法是同步的,而HashMap的方法不是。这就意味着,虽然你可以不用采取任何特殊的行为就可以在一个多线程的应用程序中用一个Hashtable,但你必须同样地为一个HashMap提供外同步。一个方便的方法就是利用Collections类的静态的synchronizedMap()方法,它创建一个线程安全的Map对象,并把它作为一个封装的对象来返回。这个对象的方法可以让你同步访问潜在的HashMap。这么做的结果就是当你不需要同步时,你不能切断Hashtable中的同步(比如在一个单线程的应用程序中),而且同步增加了很多处理费用。
第三点不同是,只有HashMap可以让你将空值作为一个表的条目的key或value。HashMap中只有一条记录可以是一个空的key,但任意数量的条目可以是空的value。这就是说,如果在表中没有发现搜索键,或者如果发现了搜索键,但它是一个空的值,那么get()将返回null。如果有必要,用containKey()方法来区别这两种情况。
一些资料建议,当需要同步时,用Hashtable,反之用HashMap。但是,因为在需要时,HashMap可以被同步,HashMap的功能比Hashtable的功能更多,而且它不是基于一个陈旧的类的,所以有人认为,在各种情况下,HashMap都优先于Hashtable。
关于Properties
有时侯,你可能想用一个hashtable来映射key的字符串到value的字符串。DOS、Windows和Unix中的环境字符串就有一些例子,如key的字符串PATH被映射到value的字符串C:\WINDOWS;C:\WINDOWS\SYSTEM。Hashtables是表示这些的一个简单的方法,但Java提供了另外一种方法。
Java.util.Properties类是Hashtable的一个子类,设计用于String keys和values。Properties对象的用法同Hashtable的用法相象,但是类增加了两个节省时间的方法,你应该知道。
Store()方法把一个Properties对象的内容以一种可读的形式保存到一个文件中。Load()方法正好相反,用来读取文件,并设定Properties对象来包含keys和values。
注意,因为Properties扩展了Hashtable,你可以用超类的put()方法来添加不是String对象的keys和values。这是不可取的。另外,如果你将store()用于一个不包含String对象的Properties对象,store()将失败。作为put()和get()的替代,你应该用setProperty()和getProperty(),它们用String参数。
好了,我希望你现在可以知道如何用hashtables来加速你的处理了。
文章来自:http://zhidao.baidu.com/question/5458097.html?fr=ala0
记得刚毕业那会准备面试,看过不少面试题,里面有个说出HashMap和HashTable不同的题目,我那会面试的时候也遇到不少次这个问题,还隐约记得当时的回答是这样的:
HashTable是比较旧的版本;HashTable是线程安全的,而HashMap是非线程安全的;HashMap的key和value允许Null值,还有就是HashMap效率要高。好像就这些了吧,当时认识也比较肤浅。
前段时间有空就想起来了这个问题,于是就想深入的理解一下这两个比较常用的数据结构,然后看了一下这两个类的源码,有了比以前更深入的了解。大体上这两个类内部处理差别不是很大,当然还是有不少不同,下面我们来一一探讨一下他们之间的不同
引言:首先来说一下HashMap内部其实是一个数组+链表的结构,当你put一个元素的时候,HashMap会根据Key的hash值算出要存放的数组的位置,如果两个元素算出的数组值相同的话,那么他们会放在数组里的同一个位置,这个时候在获取该元素的时候,那么会根据Key的hash找到数组的位置,然后再从链表中找到该元素。那么我们可以很容易的想象到,如果每一个数组里只有一个元素的时候,效率是最高的,因为不需要再对链表进行操作。有了这点认识我们就可以进行接下来的分析了。
[list]
[1]数组大小 。
既然说了内部是数组+链表,那就设计到数组的大小,这一点,HashMap和HashTable是不同的
HashMap的默认大小
Java代码
static final int DEFAULT_INITIAL_CAPACITY = 16 ;
static final int DEFAULT_INITIAL_CAPACITY = 16;
我们看到默认是16,而且HashMap的大小一定是2的幂数。这里你可能会问了,如果初始化HashMap的时候指定了一个不是2的幂数的长度呢?如果是这种情况,它也会找到一个最接近你指定值的一个2的幂数,下面是源码:
Java代码
int capacity = 1 ;
while (capacity < initialCapacity)
capacity <<= 1 ;
int capacity = 1;
while (capacity < initialCapacity)
capacity <<= 1;
就是他会找到一个比你指定值大且是2的幂数的一个值,那么为什么它会这么做呢,这个问题我留到下面具体说明。
HashMap长度最大值也是有设定的,他的最大值是
Java代码
static final int MAXIMUM_CAPACITY = 1 << 30 ;
static final int MAXIMUM_CAPACITY = 1 << 30;
如果你指定超过这个大小,它会抛弃你指定的值而采用这个默认值
Java代码
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
HashTable的默认大小
Java代码
public Hashtable() {
this ( 11 , 0 .75f);
}
public Hashtable() {
this(11, 0.75f);
}
默认是11,HashTable跟HashMap不同如果你指定了长度,它不会对你的指定值进行处理。HashTable的最大值,我没看有看到HashTable中有指定最大值的行为
[2]长度扩容
上面我们讲了两个类的初始大小,这里需要说明的事,在实际中真正利用的长度并不是这个值,而是有个加载因子,默认是0.75,比如长度是16,而真正使用的是16*0.75,当超过这个数,就会扩容
HashMap扩容
HashMap扩容会把之前长度*2,因为之前的长度肯定是2的幂数,所以自动扩容后也是2的幂数
HashTable扩容
HashTable扩容是把之前长度*2+1
扩容操作是比较消耗资源的,所以这里我们告诉我们在初始化HashMap和HashTable的时候要考虑到实际使用时的长度,应该尽可能的避免出现扩容的操作,从而提高效率
[3]put操作
HashMap的put
Java代码
public V put(K key, V value) {
K k = maskNull(key);
int hash = hash(k);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null ; e = e.next) {
if (e.hash == hash && eq(k, e.key)) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this );
return oldValue;
}
}
modCount++;
addEntry(hash, k, value, i);
return null ;
}
public V put(K key, V value) {
K k = maskNull(key);
int hash = hash(k);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
if (e.hash == hash && eq(k, e.key)) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, k, value, i);
return null;
}
我们看到首先进行maskNull,这也是为什么HashMap允许有null键;
然后是计算hash值,下面是hash方法
Java代码
static int hash(Object x) {
int h = x.hashCode();
h += ~(h << 9 );
h ^= (h >>> 14 );
h += (h << 4 );
h ^= (h >>> 10 );
return h;
}
static int hash(Object x) {
int h = x.hashCode();
h += ~(h << 9);
h ^= (h >>> 14);
h += (h << 4);
h ^= (h >>> 10);
return h;
}
这里HashMap对hash值进行处理,进行了一些列的操作,目的是为了让hash值的高位参与接下来的运算,至于为什么要用到 9,14,4,10这几个数,我也不明白,我曾经给JDK的作者之一道格发过邮件咨询这个问题,他没有给我正面的回答,而是建议我看一本书中的hash那一章节,在我查找该问题的时候,发现国外很多人也向道格咨询过此问题,得到的回到好像跟我得到的回答是一样的,嘿嘿。好了,不说题外话了,反正大家知道经过这么操作我们到了一个非负整数。接下来是计算数组下标indexFor
Java代码
static int indexFor( int h, int length) {
return h & (length- 1 );
}
static int indexFor(int h, int length) {
return h & (length-1);
}
这里的 h & (length-1)是比较出彩的地方,也是为什么前面我们介绍HashMap长度的时候,他总是2的幂数,现在我们知道为什么了吧,它实现了 h & (length-1)等价于h % length的操作,求与比求模效率要高,在道格给我的回信中也提到了这一点。也许有人会问了,这里求与的操作中hash的高位没有参与到运算,那么当 hash值高位不同时,算出的index却是相同的,那么也就是说增加了在数组中相同位置存放的对象的几率,sun其实考虑到这个问题了,这就是我前面提到的那个hash方法,这也是我向道格发邮件的原因。
put方法接下来的代码就比较简单了,大家可以自己看,提一句就是put也是有返回值的如果你存放相同的Key的话返回旧的value值,如果是不同的key返回null
HashTable的put
Java代码
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null ) {
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
Entry tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF ) % tab.length;
for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
V old = e.value;
e.value = value;
return old;
}
}
modCount++;
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();
tab = table;
index = (hash & 0x7FFFFFFF ) % tab.length;
}
// Creates the new entry.
Entry<K,V> e = tab[index];
tab[index] = new Entry<K,V>(hash, key, value, e);
count++;
return null ;
}
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
Entry tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
V old = e.value;
e.value = value;
return old;
}
}
modCount++;
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();
tab = table;
index = (hash & 0x7FFFFFFF) % tab.length;
}
// Creates the new entry.
Entry<K,V> e = tab[index];
tab[index] = new Entry<K,V>(hash, key, value, e);
count++;
return null;
}
我这里首先就是发现该put是同步的,这是和HashMap的不同。还有这里没有对hash进行处理,而是直接用hash值,在计算数组下标的时候也和HashMap不同,他这里就是采用了普通的求模操作,在求模之前对hash值进行取绝对值操作,保证计算出来的下标是正的;我们可以看出差别了,单从计算下标这一点,HashMap是比HashTable有优化的。
这里我们再来总结一下:HashMap对hash值进行了处理(处理的目的:1是为了得到一个正数,另外一个是为了在进行接下来indexFor 计算时尽可能的得到均匀的下标值);HashTable没有对hash值进行处理,只是简单的进行了一下hash & 0x7FFFFFFF操作(取绝对值);HashMap在进行index计算是使用了求与,而Hashtable采用了求模,HashMap之所以可以采用求与来替代求模前提是建立在数组长度总是2的幂数上,我们可以这么说HashMap采用了2的幂数的长度和求与的结合达到了HashTable中求模的效果,从而提高了效率。
关于HashMap和HashTable剩下的方法,我这里就不做更详细的介绍了,大家有兴趣看看应该明白了,理解了put方法,那么别的都好理解了。
[/list]
anson在这里感谢大家花了这么长时间阅读该文章,希望能给大家带了一些帮助,另外上面的分析都是我个人的理解,肯定存在一定的局限性,大家有什么更深刻的认识,还请大家指出来,我们一起交流,共同进步
文章来自:http://blog.csdn.net/lbdf001/archive/2009/12/21/5050500.aspx
发表评论
-
EHCACHE简介
2010-06-24 09:59 1250... -
web.xml里<filter-mapping>中的<dispatcher>作用
2010-06-19 09:30 1124关键字: xml里<filter-mapping> ... -
Java基本功—Reference
2010-05-25 22:22 1017这是一篇一年多之前便已写就的文章,那时,因为很多Java程 ... -
MyEclipse 8.5 开发环境配置,汉化,Aptana2.0插件,SVN 插件,Flex Builder 3/4 插件安装
2010-05-25 11:33 1283MyEclipse 8.5 开发环境配 ... -
根据IE版本不同调用不同CSS样式文件
2010-05-24 22:13 1691在webjx.com的文章中,并不提倡这样的方法,但是依然有很 ... -
java singleton
2010-05-17 17:12 1500Java singleton是指这样的类,它只能实例化一次,s ... -
搭建Android开发环境
2010-05-12 15:15 4309Android的开发现在是如火如荼,逞现在不是很忙了,学习了下 ... -
java中堆(heap)和堆栈(stack)有什么区别 备份
2010-05-12 11:24 1041stack 和 heep 都是内存的 ... -
EL表达式
2010-04-20 12:05 1194EL 全名为 Expression Language ... -
解读Tomcat服务器server.xml文件
2010-03-31 13:26 972<Server port="8005&qu ... -
Tomcat
2010-03-31 13:22 922Tomcat启动分析 1 - Tomcat Serve ... -
配置svn的问题
2010-03-02 20:04 1696Unsupported FS formatsvn: 期望文件 ... -
获取雅虎的天气情况
2010-02-24 14:02 1312package lee; import java.io.In ... -
关于解决MyEclipse 的耗内存的办法
2010-01-28 14:48 9791、老是弹出Quick update error 、关闭mye ... -
一堂如何提高代码质量的培训课(3)
2010-01-26 10:36 8653)职责驱动设计和领 ... -
一堂如何提高代码质量的培训课(2)
2010-01-26 10:35 8753.可变更性 前面我提到了,软件的变更性是所有软件理论的 ... -
一堂如何提高代码质量的培训课
2010-01-25 13:21 1023今天这堂培训课讲什么呢?我既不讲Spring,也不讲Hiber ...
相关推荐
内容概要:本文详细介绍了基于MATLAB GUI界面和卷积神经网络(CNN)的模糊车牌识别系统。该系统旨在解决现实中车牌因模糊不清导致识别困难的问题。文中阐述了整个流程的关键步骤,包括图像的模糊还原、灰度化、阈值化、边缘检测、孔洞填充、形态学操作、滤波操作、车牌定位、字符分割以及最终的字符识别。通过使用维纳滤波或最小二乘法约束滤波进行模糊还原,再利用CNN的强大特征提取能力完成字符分类。此外,还特别强调了MATLAB GUI界面的设计,使得用户能直观便捷地操作整个系统。 适合人群:对图像处理和深度学习感兴趣的科研人员、高校学生及从事相关领域的工程师。 使用场景及目标:适用于交通管理、智能停车场等领域,用于提升车牌识别的准确性和效率,特别是在面对模糊车牌时的表现。 其他说明:文中提供了部分关键代码片段作为参考,并对实验结果进行了详细的分析,展示了系统在不同环境下的表现情况及其潜在的应用前景。
嵌入式八股文面试题库资料知识宝典-计算机专业试题.zip
嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_3.zip
内容概要:本文深入探讨了一款额定功率为4kW的开关磁阻电机,详细介绍了其性能参数如额定功率、转速、效率、输出转矩和脉动率等。同时,文章还展示了利用RMxprt、Maxwell 2D和3D模型对该电机进行仿真的方法和技术,通过外电路分析进一步研究其电气性能和动态响应特性。最后,文章提供了基于RMxprt模型的MATLAB仿真代码示例,帮助读者理解电机的工作原理及其性能特点。 适合人群:从事电机设计、工业自动化领域的工程师和技术人员,尤其是对开关磁阻电机感兴趣的科研工作者。 使用场景及目标:适用于希望深入了解开关磁阻电机特性和建模技术的研究人员,在新产品开发或现有产品改进时作为参考资料。 其他说明:文中提供的代码示例仅用于演示目的,实际操作时需根据所用软件的具体情况进行适当修改。
少儿编程scratch项目源代码文件案例素材-剑客冲刺.zip
少儿编程scratch项目源代码文件案例素材-几何冲刺 转瞬即逝.zip
内容概要:本文详细介绍了基于PID控制器的四象限直流电机速度驱动控制系统仿真模型及其永磁直流电机(PMDC)转速控制模型。首先阐述了PID控制器的工作原理,即通过对系统误差的比例、积分和微分运算来调整电机的驱动信号,从而实现转速的精确控制。接着讨论了如何利用PID控制器使有刷PMDC电机在四个象限中精确跟踪参考速度,并展示了仿真模型在应对快速负载扰动时的有效性和稳定性。最后,提供了Simulink仿真模型和详细的Word模型说明文档,帮助读者理解和调整PID控制器参数,以达到最佳控制效果。 适合人群:从事电力电子与电机控制领域的研究人员和技术人员,尤其是对四象限直流电机速度驱动控制系统感兴趣的读者。 使用场景及目标:适用于需要深入了解和掌握四象限直流电机速度驱动控制系统设计与实现的研究人员和技术人员。目标是在实际项目中能够运用PID控制器实现电机转速的精确控制,并提高系统的稳定性和抗干扰能力。 其他说明:文中引用了多篇相关领域的权威文献,确保了理论依据的可靠性和实用性。此外,提供的Simulink模型和Word文档有助于读者更好地理解和实践所介绍的内容。
嵌入式八股文面试题库资料知识宝典-2013年海康威视校园招聘嵌入式开发笔试题.zip
少儿编程scratch项目源代码文件案例素材-驾驶通关.zip
小区开放对周边道路通行能力影响的研究.pdf
内容概要:本文探讨了冷链物流车辆路径优化问题,特别是如何通过NSGA-2遗传算法和软硬时间窗策略来实现高效、环保和高客户满意度的路径规划。文中介绍了冷链物流的特点及其重要性,提出了软时间窗概念,允许一定的配送时间弹性,同时考虑碳排放成本,以达到绿色物流的目的。此外,还讨论了如何将客户满意度作为路径优化的重要评价标准之一。最后,通过一段简化的Python代码展示了遗传算法的应用。 适合人群:从事物流管理、冷链物流运营的专业人士,以及对遗传算法和路径优化感兴趣的科研人员和技术开发者。 使用场景及目标:适用于冷链物流企业,旨在优化配送路线,降低运营成本,减少碳排放,提升客户满意度。目标是帮助企业实现绿色、高效的物流配送系统。 其他说明:文中提供的代码仅为示意,实际应用需根据具体情况调整参数设置和模型构建。
少儿编程scratch项目源代码文件案例素材-恐怖矿井.zip
内容概要:本文详细介绍了基于STM32F030的无刷电机控制方案,重点在于高压FOC(磁场定向控制)技术和滑膜无感FOC的应用。该方案实现了过载、过欠压、堵转等多种保护机制,并提供了完整的源码、原理图和PCB设计。文中展示了关键代码片段,如滑膜观测器和电流环处理,以及保护机制的具体实现方法。此外,还提到了方案的移植要点和实际测试效果,确保系统的稳定性和高效性。 适合人群:嵌入式系统开发者、电机控制系统工程师、硬件工程师。 使用场景及目标:适用于需要高性能无刷电机控制的应用场景,如工业自动化设备、无人机、电动工具等。目标是提供一种成熟的、经过验证的无刷电机控制方案,帮助开发者快速实现并优化电机控制性能。 其他说明:提供的资料包括详细的原理图、PCB设计文件、源码及测试视频,方便开发者进行学习和应用。
基于有限体积法Godunov格式的管道泄漏检测模型研究.pdf
嵌入式八股文面试题库资料知识宝典-CC++笔试题-深圳有为(2019.2.28)1.zip
少儿编程scratch项目源代码文件案例素材-几何冲刺 V1.5.zip
Android系统开发_Linux内核配置_USB-HID设备模拟_通过root权限将Android设备转换为全功能USB键盘的项目实现_该项目需要内核支持configFS文件系统
C# WPF - LiveCharts Project
少儿编程scratch项目源代码文件案例素材-恐怖叉子 动画.zip
嵌入式八股文面试题库资料知识宝典-嵌⼊式⼯程师⾯试⾼频问题.zip