仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1242|回复: 19
打印 上一主题 下一主题

[学习教程] JAVA编程:Java 实际与理论: 哈希

[复制链接]
蒙在股里 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-18 11:43:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
通过视频学习比传统的大课堂学习更适合成人化的学习规律。有人说大课堂气氛好,学习氛围浓,热闹,可以认识很多人。每一个Java对象都有hashCode()和equals()办法。很多类疏忽(Override)这些办法的缺省实行,以在对象实例之间供应更深条理的语义可比性。在Java理念和理论这一部分,Java开辟职员BrianGoetz向您先容在创立Java类以无效和正确界说hashCode()和equals()时应遵守的划定规矩和指南。您能够在会商论坛与作者和别的读者一同切磋您对本文的意见。(您还能够点击本文顶部或底部的会商进进论坛。)
固然Java言语不间接撑持联系关系数组--可使用任何对象作为一个索引的数组--但在根Object类中利用hashCode()办法明白暗示希冀普遍利用HashMap(及其先辈Hashtable)。幻想情形下基于散列的容器供应无效拔出和无效检索;间接在对象形式中撑持散列能够增进基于散列的容器的开辟和利用。

界说对象的相称性
Object类有两种办法来揣度对象的标识:equals()和hashCode()。一样平常来讲,假如您疏忽了个中一种,您必需同时疏忽这两种,由于二者之间有必需保持的相当主要的干系。特别情形是依据equals()办法,假如两个对象是相称的,它们必需有不异的hashCode()值(只管这一般不是真的)。

特定类的equals()的语义在Implementer的左边界说;界说对特定类来讲equals()意味着甚么是其计划事情的一部分。Object供应的缺省实行复杂援用上面等式:


publicbooleanequals(Objectobj){return(this==obj);}



在这类缺省实行情形下,只要它们援用真正统一个对象时这两个援用才是相称的。一样,Object供应的hashCode()的缺省实行经由过程将对象的内存地点对映于一个整数值来天生。因为在某些架构上,地点空间年夜于int值的局限,两个分歧的对象有不异的hashCode()是大概的。假如您疏忽了hashCode(),您仍然可使用System.identityHashCode()办法来接进这类缺省值。

疏忽equals()--复杂实例
缺省情形下,equals()和hashCode()基于标识的实行是公道的,但关于某些类来讲,它们但愿放宽等式的界说。比方,Integer类界说equals()与上面相似:


publicbooleanequals(Objectobj){
return(objinstanceofInteger
&&intValue()==((Integer)obj).intValue());
}



在这个界说中,只要在包括不异的整数值的情形下这两个Integer对象是相称的。分离将不成修正的Integer,这使得利用Integer作为HashMap中的关头字是实在可行的。这类基于值的Equal办法能够由Java类库中的一切原始封装类利用,如Integer、Float、Character和Boolean和String(假如两个String对象包括不异按次的字符,那它们是相称的)。因为这些类都是不成修正的而且能够实行hashCode()和equals(),它们都能够做为很好的散列关头字。

为何疏忽equals()和hashCode()?
假如Integer不疏忽equals()和hashCode()情形又将怎样?假如我们从未在HashMap或别的基于散列的汇合中利用Integer作为关头字的话,甚么也不会产生。可是,假如我们在HashMap中利用这类Integer对象作为关头字,我们将不克不及够牢靠地检索相干的值,除非我们在get()挪用中利用与put()挪用中极为相似的Integer实例。这请求确保在我们的全部程序中,只能利用对应于特定整数值的Integer对象的一个实例。不必说,这类办法极不便利并且毛病一再。

Object的interfacecontract请求假如依据equals()两个对象是相称的,那末它们必需有不异的hashCode()值。当其辨认才能全部包括在equals()中时,为何我们的根对象类必要hashCode()?hashCode()办法地道用于进步效力。Java平台计划职员估计到了典范Java使用程序中基于散列的汇合类(CollectionClass)的主要性--如Hashtable、HashMap和HashSet,而且利用equals()与很多对象举行对照在盘算方面十分高贵。使一切Java对象都可以撑持hashCode()并分离利用基于散列的汇合,能够完成无效的存储和检索。

实行equals()和hashCode()的需求
实行equals()和hashCode()有一些限定,Object文件中枚举出了这些限定。出格是equals()办法必需显现以上司性:

Symmetry:两个援用,a和b,a.equals(b)ifandonlyifb.equals(a)
Reflexivity:一切非空援用,a.equals(a)
Transitivity:Ifa.equals(b)andb.equals(c),thena.equals(c)
ConsistencywithhashCode():两个相称的对象必需有不异的hashCode()值
Object的标准中并没有明白请求equals()和hashCode()必需分歧--它们的了局在随后的挪用中将是不异的,假定“不改动对象相称性对照中利用的任何信息。”这听起来象“盘算的了局将不改动,除非实践情形云云。”这一含混声明一般注释为相称性和散列值盘算应是对象的可断定性功效,而不是别的。

对象相称性意味着甚么?
人们很简单满意Object类标准对equals()和hashCode()的请求。决意是不是和怎样疏忽equals()除判别之外,还请求别的。在复杂的不成修值类中,如Integer(现实上是几近一切不成修正的类),选择相称分明--相称性应基于基础对象形态的相称性。在Integer情形下,对象的独一形态是基础的整数值。

关于可修正对象来讲,谜底其实不老是云云分明。equals()和hashCode()是不是应基于对象的标识(象缺省实行)或对象的形态(象Integer和String)?没有复杂的谜底--它取决于类的企图利用。关于象List和Map如许的容器来讲,人们对此争辩不已。Java类库中的年夜多半类,包含容器类,毛病呈现在依据对象形态来供应equals()和hashCode()实行。

假如对象的hashCode()值能够基于其形态举行变动,那末当利用这类对象作为基于散列的汇合中的关头字时我们必需注重,确保当它们用于作为散列关头字时,我们其实不同意变动它们的形态。一切基于散列的汇合假定,当对象的散列值用于作为汇合中的关头字时它不会改动。假如当关头字在汇合中时它的散列代码被变动,那末将发生一些不成展望和简单搅浑的了局。理论过程当中这一般不是成绩--我们其实不常常利用象List如许的可修正对象做为HashMap中的关头字。

一个复杂的可修正类的例子是Point,它依据形态来界说equals()和hashCode()。假如两个Point对象援用不异的(x,y)座标,Point的散列值来历于x和y座标值的IEEE754-bit暗示,那末它们是相称的。

关于对照庞大的类来讲,equals()和hashCode()的举动大概乃至遭到superclass或interface的影响。比方,List接口请求假如而且只要另外一个对象是List,并且它们有不异按次的不异的Elements(由Element上的Object.equals()界说),List对象即是另外一个对象。hashCode()的需求更特别--list的hashCode()值必需切合以下盘算:


hashCode=1;
Iteratori=list.iterator();
while(i.hasNext()){
Objectobj=i.next();
hashCode=31*hashCode+(obj==null?0:obj.hashCode());
}



不单单散列值取决于list的内容,并且还划定了却合各个Element的散列值的特别算法。(String类划定相似的算法用于盘算String的散列值。)

编写本人的equals()和hashCode()办法
疏忽缺省的equals()办法对照复杂,但假如不违背对称(Symmetry)或传送性(Transitivity)需求,疏忽已疏忽的equals()办法极为辣手。当疏忽equals()时,您应当老是在equals()中包含一些Javadoc正文,以匡助那些但愿可以准确扩大您的类的用户。

作为一个复杂的例子,思索以下类:


classA{
finalBsomeNonNullField;
CsomeOtherField;
intsomeNonStateField;
}



我们应怎样编写该类的equals()的办法?这类办法合用于很多情形:


publicbooleanequals(Objectother){
//Notstrictlynecessary,butoftenagoodoptimization
if(this==other)
returntrue;
if(!(otherinstanceofA))
returnfalse;
AotherA=(A)other;
return
(someNonNullField.equals(otherA.someNonNullField))
&&((someOtherField==null)
?otherA.someOtherField==null
:someOtherField.equals(otherA.someOtherField)));
}



如今我们界说了equals(),我们必需以一致的办法来界说hashCode()。一种一致但其实不老是无效的界说hashCode()的办法以下:


publicinthashCode(){return0;}



这类办法将天生大批的条目并明显下降HashMaps的功能,但它切合标准。一个更公道的hashCode()实行应当是如许:


publicinthashCode(){
inthash=1;
hash=hash*31+someNonNullField.hashCode();
hash=hash*31
+(someOtherField==null?0:someOtherField.hashCode());
returnhash;
}



注重:这两种实行都下降了类形态字段的equals()或hashCode()办法必定比例的盘算才能。依据您利用的类,您大概但愿下降superclass的equals()或hashCode()功效一部分盘算才能。关于原始字段来讲,在相干的封装类中有helper功效,能够匡助创立散列值,如Float.floatToIntBits。

编写一个完善的equals()办法是不实际的。一般,当扩大一个本身疏忽了equals()的instantiable类时,疏忽equals()是不实在际的,并且编写将被疏忽的equals()办法(如在笼统类中)分歧于为详细类编写equals()办法。关于实例和申明的更具体信息请参阅EffectiveJavaProgrammingLanguageGuide,Item7(参考材料)。

有待改善?
将散列法构建到Java类库的根对象类中是一种十分明智的计划折中办法--它使利用基于散列的容器变得云云复杂和高效。可是,人们对Java类库中的散列算法和对象相称性的办法和实行提出了很多品评。java.util中基于散列的容器十分便利和烦琐易用,但大概不合用于必要十分高功能的使用程序。固然个中年夜部分将不会改动,但当您计划严峻依附于基于散列的容器效力的使用程序时必需思索这些要素,它们包含:

太小的散列局限。利用int而不是long作为hashCode()的前往范例增添了散列抵触的概率。


糟的散列值分派。短strings和小型integers的散列值是它们本人的小整数,靠近于别的“临近”对象的散列值。一个循规导矩(Well-behaved)的散列函数将在该散列局限内更匀称地分派散列值。


无界说的散列操纵。固然某些类,如String和List,界说了将其Element的散列值分离到一个散列值中利用的散列算法,但言语标准不界说将多个对象的散列值分离到新散列值中的任何同意的办法。我们在后面编写本人的equals()和hashCode()办法中会商的List、String或实例类A利用的窍门都很复杂,但算术上还远远不敷完善。类库不供应任何散列算法的便利实行,它能够简化更先辈的hashCode()实行的创立。


当扩大已疏忽了equals()的instantiable类时很难编写equals()。当扩大已疏忽了equals()的instantiable类时,界说equals()的“不言而喻的”体例都不克不及满意equals()办法的对称或传送性需求。这意味着当疏忽equals()时,您必需懂得您正在扩大的类的布局和实行具体信息,乃至必要表露基础类中的秘密字段,它违背了面向对象的计划的准绳。
停止语
经由过程一致界说equals()和hashCode(),您能够提拔类作为基于散列的汇合中的关头字的利用性。有两种办法来界说对象的相称性和散列值:基于标识,它是Object供应的缺省办法;基于形态,它请求疏忽equals()和hashCode()。当对象的形态变动时假如对象的散列值产生变更,确信当形态作为散列关头字利用时您不同意更变动其形态。

手机用到的是用j2me所编出来的小程序。
若天明 该用户已被删除
沙发
发表于 2015-1-21 13:19:51 | 只看该作者
有时间再研究一下MVC结构(把Model-View-Control分离开的设计思想)
小魔女 该用户已被删除
板凳
发表于 2015-1-23 11:43:39 | 只看该作者
你快去找一份Java的编程工作来做吧(如果是在校学生可以去做兼职啊),在实践中提高自己,那才是最快的。不过你得祈祷在公司里碰到一个高手,而且他 还愿意不厌其烦地教你,这样好象有点难哦!还有一个办法就是读开放源码的程序了。我们知道开放源码大都出自高手,他们设计合理,考虑周到,再加上有广大的程序员参与,代码的价值自然是字字珠叽,铿锵有力(对不起,偶最近《金装四大才子》看多了)。
兰色精灵 该用户已被删除
地板
发表于 2015-1-25 22:49:17 | 只看该作者
你可以去承接一些项目做了,一开始可能有些困难,可是你有技术积累,又考虑周全,接下项目来可以迅速作完,相信大家以后都会来找你的,所以Money就哗啦啦的。。。。。。
蒙在股里 该用户已被删除
5#
 楼主| 发表于 2015-1-27 08:34:41 | 只看该作者
那么我书也看了,程序也做了,别人问我的问题我都能解决了,是不是就成为高手了呢?当然没那么简单,这只是万里长征走完了第一步。不信?那你出去接一个项目,你知道怎么下手吗,你知道怎么设计吗,你知道怎么组织人员进行开发吗?你现在脑子里除了一些散乱的代码之外,可能再没有别的东西了吧!
简单生活 该用户已被删除
6#
发表于 2015-2-3 22:00:12 | 只看该作者
Java自面世后就非常流行,发展迅速,对C++语言形成了有力冲击。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于个人PC、数据中心、游戏控制台
爱飞 该用户已被删除
7#
发表于 2015-2-9 05:32:55 | 只看该作者
你现在最缺的是实际的工作经验,而不是书本上那些凭空想出来的程序。
莫相离 该用户已被删除
8#
发表于 2015-2-27 00:50:35 | 只看该作者
吧,现在很流行的Structs就是它的一种实现方式,不过Structs用起来实在是很繁,我们只要学习其精髓即可,我们完全可以设计自己的MVC结构。然后你再研究一下软件Refactoring (重构)和极限XP编程,相信你又会上一个台阶。 做完这些,你不如整理一下你的Java代码,把那些经典的程序和常见的应用整理出来,再精心打造一番,提高其重用性和可扩展性。你再找几个志同道合的朋友成立一个工作室吧
分手快乐 该用户已被删除
9#
发表于 2015-3-6 20:47:11 | 只看该作者
是一种将安全性(Security)列为第一优先考虑的语言
精灵巫婆 该用户已被删除
10#
发表于 2015-3-11 03:34:46 | 只看该作者
多重继承(以接口取代)等特性,增加了垃圾回收器功能用于回收不再被引用的对象所占据的内存空间,使得程序员不用再为内存管理而担忧。在 Java 1.5 版本中,Java 又引入了泛型编程(Generic Programming)、类型安全的枚举、不定长参数和自动装/拆箱等语言特性。
变相怪杰 该用户已被删除
11#
发表于 2015-3-13 08:07:15 | 只看该作者
Java是一个纯的面向对象的程序设计语言,它继承了 C++语言面向对象技术的核心。Java舍弃了C ++语言中容易引起错误的指针(以引用取代)、运算符重载(operator overloading)
老尸 该用户已被删除
12#
发表于 2015-3-20 16:43:02 | 只看该作者
多重继承(以接口取代)等特性,增加了垃圾回收器功能用于回收不再被引用的对象所占据的内存空间,使得程序员不用再为内存管理而担忧。在 Java 1.5 版本中,Java 又引入了泛型编程(Generic Programming)、类型安全的枚举、不定长参数和自动装/拆箱等语言特性。
柔情似水 该用户已被删除
13#
发表于 2015-3-20 18:46:02 | 只看该作者
不过,每次的执行编译后的字节码需要消耗一定的时间,这同时也在一定程度上降低了 Java 程序的运行效率。
小妖女 该用户已被删除
14#
发表于 2015-3-25 08:57:59 | 只看该作者
Java 编程语言的风格十分接近C、C++语言。
透明 该用户已被删除
15#
发表于 2015-4-2 12:57:21 | 只看该作者
是一种使网页(Web Page)由静态(Static)转变为动态(Dynamic)的语言
山那边是海 该用户已被删除
16#
发表于 2015-4-3 02:48:28 | 只看该作者
在全球云计算和移动互联网的产业环境下,Java更具备了显著优势和广阔前景。
金色的骷髅 该用户已被删除
17#
发表于 2015-4-21 07:13:12 | 只看该作者
吧,现在很流行的Structs就是它的一种实现方式,不过Structs用起来实在是很繁,我们只要学习其精髓即可,我们完全可以设计自己的MVC结构。然后你再研究一下软件Refactoring (重构)和极限XP编程,相信你又会上一个台阶。 做完这些,你不如整理一下你的Java代码,把那些经典的程序和常见的应用整理出来,再精心打造一番,提高其重用性和可扩展性。你再找几个志同道合的朋友成立一个工作室吧
活着的死人 该用户已被删除
18#
发表于 2015-4-28 03:07:23 | 只看该作者
关于设计模式的资料,还是向大家推荐banq的网站 [url]http://www.jdon.com/[/url],他把GOF的23种模式以通俗易懂的方式诠释出来,纯Java描述,真是经典中的经典。
因胸联盟 该用户已被删除
19#
发表于 2015-5-1 06:16:28 | 只看该作者
你可以去承接一些项目做了,一开始可能有些困难,可是你有技术积累,又考虑周全,接下项目来可以迅速作完,相信大家以后都会来找你的,所以Money就哗啦啦的。。。。。。
只想知道 该用户已被删除
20#
发表于 2015-6-12 21:11:55 | 只看该作者
是一种使网页(Web Page)产生生动活泼画面的语言
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-22 20:59

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表