仓酷云

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

[学习教程] 发布一篇Java汇合进修(十) HashMap具体先容(源码剖析)和利用示例

[复制链接]
灵魂腐蚀 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-18 11:00:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
java主要分三块,j2se:java的基础核心语言。j2me:java的微型模块,专门针对内存小,没有持续电源等小型设备。j2ee:java的企业模块,专门针对企业数据库服务器的连接维护。
这一章,我们对HashMap举行进修。
我们先对HashMap有个全体熟悉,然后再进修它的源码,最初再经由过程实例来学会利用HashMap。
第1部分HashMap先容
HashMap简介
HashMap是一个散列表,它存储的内容是键值对(key-value)映照。
HashMap承继于AbstractMap,完成了Map、Cloneable、java.io.Serializable接口。
HashMap的完成不是同步的,这意味着它不是线程平安的。它的key、value都能够为null。别的,HashMap中的映照不是有序的。
HashMap的实例有两个参数影响其功能:“初始容量”和“加载因子”。容量是哈希表中桶的数目,初始容量只是哈希表在创立时的容量。加载因子是哈希表在其容量主动增添之前能够到达多满的一种标准。当哈希表中的条目数超越了加载因子与以后容量的乘积时,则要对该哈希表举行rehash操纵(即重修外部数据布局),从而哈希表将具有约莫两倍的桶数。
一般,默许加载因子是0.75,这是在工夫和空间本钱上追求一种折中。加载因子太高固然削减了空间开支,但同时也增添了查询本钱(在年夜多半HashMap类的操纵中,包含get和put操纵,都反应了这一点)。在设置初始容量时应当思索到映照中所需的条目数及其加载因子,以便最年夜限制地削减rehash操纵次数。假如初始容量年夜于最年夜条目数除以加载因子,则不会产生rehash操纵。
HashMap的承继干系
  1. java.lang.Object
  2. java.util.AbstractMap<K,V>
  3. java.util.HashMap<K,V>
  4. publicclassHashMap<K,V>
  5. extendsAbstractMap<K,V>
  6. implementsMap<K,V>,Cloneable,Serializable{}
复制代码
HashMap与Map干系以下图:

HashMap的机关函数
HashMap共有4个机关函数,以下:
  1. //默许机关函数。
  2. HashMap()
  3. //指定“容量巨细”的机关函数
  4. HashMap(intcapacity)
  5. //指定“容量巨细”和“加载因子”的机关函数
  6. HashMap(intcapacity,floatloadFactor)
  7. //包括“子Map”的机关函数
  8. HashMap(Map<?extendsK,?extendsV>map)
复制代码
HashMap的API
  1. voidclear()
  2. Objectclone()
  3. booleancontainsKey(Objectkey)
  4. booleancontainsValue(Objectvalue)
  5. Set<Entry<K,V>>entrySet()
  6. Vget(Objectkey)
  7. booleanisEmpty()
  8. Set<K>keySet()
  9. Vput(Kkey,Vvalue)
  10. voidputAll(Map<?extendsK,?extendsV>map)
  11. Vremove(Objectkey)
  12. intsize()
  13. Collection<V>values()
复制代码
第2部分HashMap源码剖析
为了更懂得HashMap的道理,上面对HashMap源码代码作出剖析。
在浏览源码时,倡议参考前面的申明来创建对HashMap的全体熟悉,如许更简单了解HashMap。
  1. packagejava.util;
  2. importjava.io.*;
  3. publicclassHashMap<K,V>
  4. extendsAbstractMap<K,V>
  5. implementsMap<K,V>,Cloneable,Serializable
  6. {
  7. //默许的初始容量是16,必需是2的幂。
  8. staticfinalintDEFAULT_INITIAL_CAPACITY=16;
  9. //最年夜容量(必需是2的幂且小于2的30次方,传进容量过上将被这个值交换)
  10. staticfinalintMAXIMUM_CAPACITY=1<<30;
  11. //默许加载因子
  12. staticfinalfloatDEFAULT_LOAD_FACTOR=0.75f;
  13. //存储数据的Entry数组,长度是2的幂。
  14. //HashMap是接纳拉链法完成的,每个Entry实质上是一个单向链表
  15. transientEntry[]table;
  16. //HashMap的巨细,它是HashMap保留的键值对的数目
  17. transientintsize;
  18. //HashMap的阈值,用于判别是不是必要调剂HashMap的容量(threshold=容量*加载因子)
  19. intthreshold;
  20. //加载因籽实际巨细
  21. finalfloatloadFactor;
  22. //HashMap被改动的次数
  23. transientvolatileintmodCount;
  24. //指定“容量巨细”和“加载因子”的机关函数
  25. publicHashMap(intinitialCapacity,floatloadFactor){
  26. if(initialCapacity<0)
  27. thrownewIllegalArgumentException("Illegalinitialcapacity:"+
  28. initialCapacity);
  29. //HashMap的最年夜容量只能是MAXIMUM_CAPACITY
  30. if(initialCapacity>MAXIMUM_CAPACITY)
  31. initialCapacity=MAXIMUM_CAPACITY;
  32. if(loadFactor<=0||Float.isNaN(loadFactor))
  33. thrownewIllegalArgumentException("Illegalloadfactor:"+
  34. loadFactor);
  35. //找出“年夜于initialCapacity”的最小的2的幂
  36. intcapacity=1;
  37. while(capacity<initialCapacity)
  38. capacity<<=1;
  39. //设置“加载因子”
  40. this.loadFactor=loadFactor;
  41. //设置“HashMap阈值”,当HashMap中存储数据的数目到达threshold时,就必要将HashMap的容量更加。
  42. threshold=(int)(capacity*loadFactor);
  43. //创立Entry数组,用来保留数据
  44. table=newEntry[capacity];
  45. init();
  46. }
  47. //指定“容量巨细”的机关函数
  48. publicHashMap(intinitialCapacity){
  49. this(initialCapacity,DEFAULT_LOAD_FACTOR);
  50. }
  51. //默许机关函数。
  52. publicHashMap(){
  53. //设置“加载因子”
  54. this.loadFactor=DEFAULT_LOAD_FACTOR;
  55. //设置“HashMap阈值”,当HashMap中存储数据的数目到达threshold时,就必要将HashMap的容量更加。
  56. threshold=(int)(DEFAULT_INITIAL_CAPACITY*DEFAULT_LOAD_FACTOR);
  57. //创立Entry数组,用来保留数据
  58. table=newEntry[DEFAULT_INITIAL_CAPACITY];
  59. init();
  60. }
  61. //包括“子Map”的机关函数
  62. publicHashMap(Map<?extendsK,?extendsV>m){
  63. this(Math.max((int)(m.size()/DEFAULT_LOAD_FACTOR)+1,
  64. DEFAULT_INITIAL_CAPACITY),DEFAULT_LOAD_FACTOR);
  65. //将m中的全体元素逐一增加到HashMap中
  66. putAllForCreate(m);
  67. }
  68. staticinthash(inth){
  69. h^=(h>>>20)^(h>>>12);
  70. returnh^(h>>>7)^(h>>>4);
  71. }
  72. //前往索引值
  73. //h&(length-1)包管前往值的小于length
  74. staticintindexFor(inth,intlength){
  75. returnh&(length-1);
  76. }
  77. publicintsize(){
  78. returnsize;
  79. }
  80. publicbooleanisEmpty(){
  81. returnsize==0;
  82. }
  83. //猎取key对应的value
  84. publicVget(Objectkey){
  85. if(key==null)
  86. returngetForNullKey();
  87. //猎取key的hash值
  88. inthash=hash(key.hashCode());
  89. //在“该hash值对应的链表”上查找“键值即是key”的元素
  90. for(Entry<K,V>e=table[indexFor(hash,table.length)];
  91. e!=null;
  92. e=e.next){
  93. Objectk;
  94. if(e.hash==hash&&((k=e.key)==key||key.equals(k)))
  95. returne.value;
  96. }
  97. returnnull;
  98. }
  99. //猎取“key为null”的元素的值
  100. //HashMap将“key为null”的元素存储在table[0]地位!
  101. privateVgetForNullKey(){
  102. for(Entry<K,V>e=table[0];e!=null;e=e.next){
  103. if(e.key==null)
  104. returne.value;
  105. }
  106. returnnull;
  107. }
  108. //HashMap是不是包括key
  109. publicbooleancontainsKey(Objectkey){
  110. returngetEntry(key)!=null;
  111. }
  112. //前往“键为key”的键值对
  113. finalEntry<K,V>getEntry(Objectkey){
  114. //猎取哈希值
  115. //HashMap将“key为null”的元素存储在table[0]地位,“key不为null”的则挪用hash()盘算哈希值
  116. inthash=(key==null)?0:hash(key.hashCode());
  117. //在“该hash值对应的链表”上查找“键值即是key”的元素
  118. for(Entry<K,V>e=table[indexFor(hash,table.length)];
  119. e!=null;
  120. e=e.next){
  121. Objectk;
  122. if(e.hash==hash&&
  123. ((k=e.key)==key||(key!=null&&key.equals(k))))
  124. returne;
  125. }
  126. returnnull;
  127. }
  128. //将“key-value”增加到HashMap中
  129. publicVput(Kkey,Vvalue){
  130. //若“key为null”,则将该键值对增加到table[0]中。
  131. if(key==null)
  132. returnputForNullKey(value);
  133. //若“key不为null”,则盘算该key的哈希值,然后将其增加到该哈希值对应的链表中。
  134. inthash=hash(key.hashCode());
  135. inti=indexFor(hash,table.length);
  136. for(Entry<K,V>e=table[i];e!=null;e=e.next){
  137. Objectk;
  138. //若“该key”对应的键值对已存在,则用新的value代替旧的value。然前进出!
  139. if(e.hash==hash&&((k=e.key)==key||key.equals(k))){
  140. VoldValue=e.value;
  141. e.value=value;
  142. e.recordAccess(this);
  143. returnoldValue;
  144. }
  145. }
  146. //若“该key”对应的键值对不存在,则将“key-value”增加到table中
  147. modCount++;
  148. addEntry(hash,key,value,i);
  149. returnnull;
  150. }
  151. //putForNullKey()的感化是将“key为null”键值对增加到table[0]地位
  152. privateVputForNullKey(Vvalue){
  153. for(Entry<K,V>e=table[0];e!=null;e=e.next){
  154. if(e.key==null){
  155. VoldValue=e.value;
  156. e.value=value;
  157. e.recordAccess(this);
  158. returnoldValue;
  159. }
  160. }
  161. //这里的完整不会被实行到!
  162. modCount++;
  163. addEntry(0,null,value,0);
  164. returnnull;
  165. }
  166. //创立HashMap对应的“增加办法”,
  167. //它和put()分歧。putForCreate()是外部办法,它被机关函数等挪用,用来创立HashMap
  168. //而put()是对外供应的往HashMap中增加元素的办法。
  169. privatevoidputForCreate(Kkey,Vvalue){
  170. inthash=(key==null)?0:hash(key.hashCode());
  171. inti=indexFor(hash,table.length);
  172. //若该HashMap表中存在“键值即是key”的元素,则交换该元素的value值
  173. for(Entry<K,V>e=table[i];e!=null;e=e.next){
  174. Objectk;
  175. if(e.hash==hash&&
  176. ((k=e.key)==key||(key!=null&&key.equals(k)))){
  177. e.value=value;
  178. return;
  179. }
  180. }
  181. //若该HashMap表中不存在“键值即是key”的元素,则将该key-value增加到HashMap中
  182. createEntry(hash,key,value,i);
  183. }
  184. //将“m”中的全体元素都增加到HashMap中。
  185. //该办法被外部的机关HashMap的办法所挪用。
  186. privatevoidputAllForCreate(Map<?extendsK,?extendsV>m){
  187. //使用迭代器将元素逐一增加到HashMap中
  188. for(Iterator<?extendsMap.Entry<?extendsK,?extendsV>>i=m.entrySet().iterator();i.hasNext();){
  189. Map.Entry<?extendsK,?extendsV>e=i.next();
  190. putForCreate(e.getKey(),e.getValue());
  191. }
  192. }
  193. //从头调剂HashMap的巨细,newCapacity是调剂后的单元
  194. voidresize(intnewCapacity){
  195. Entry[]oldTable=table;
  196. intoldCapacity=oldTable.length;
  197. if(oldCapacity==MAXIMUM_CAPACITY){
  198. threshold=Integer.MAX_VALUE;
  199. return;
  200. }
  201. //新建一个HashMap,将“旧HashMap”的全体元素增加到“新HashMap”中,
  202. //然后,将“新HashMap”赋值给“旧HashMap”。
  203. Entry[]newTable=newEntry[newCapacity];
  204. transfer(newTable);
  205. table=newTable;
  206. threshold=(int)(newCapacity*loadFactor);
  207. }
  208. //将HashMap中的全体元素都增加到newTable中
  209. voidtransfer(Entry[]newTable){
  210. Entry[]src=table;
  211. intnewCapacity=newTable.length;
  212. for(intj=0;j<src.length;j++){
  213. Entry<K,V>e=src[j];
  214. if(e!=null){
  215. src[j]=null;
  216. do{
  217. Entry<K,V>next=e.next;
  218. inti=indexFor(e.hash,newCapacity);
  219. e.next=newTable[i];
  220. newTable[i]=e;
  221. e=next;
  222. }while(e!=null);
  223. }
  224. }
  225. }
  226. //将"m"的全体元素都增加到HashMap中
  227. publicvoidputAll(Map<?extendsK,?extendsV>m){
  228. //无效性判别
  229. intnumKeysToBeAdded=m.size();
  230. if(numKeysToBeAdded==0)
  231. return;
  232. //盘算容量是不是充足,
  233. //若“以后实践容量<必要的容量”,则将容量x2。
  234. if(numKeysToBeAdded>threshold){
  235. inttargetCapacity=(int)(numKeysToBeAdded/loadFactor+1);
  236. if(targetCapacity>MAXIMUM_CAPACITY)
  237. targetCapacity=MAXIMUM_CAPACITY;
  238. intnewCapacity=table.length;
  239. while(newCapacity<targetCapacity)
  240. newCapacity<<=1;
  241. if(newCapacity>table.length)
  242. resize(newCapacity);
  243. }
  244. //经由过程迭代器,将“m”中的元素逐一增加到HashMap中。
  245. for(Iterator<?extendsMap.Entry<?extendsK,?extendsV>>i=m.entrySet().iterator();i.hasNext();){
  246. Map.Entry<?extendsK,?extendsV>e=i.next();
  247. put(e.getKey(),e.getValue());
  248. }
  249. }
  250. //删除“键为key”元素
  251. publicVremove(Objectkey){
  252. Entry<K,V>e=removeEntryForKey(key);
  253. return(e==null?null:e.value);
  254. }
  255. //删除“键为key”的元素
  256. finalEntry<K,V>removeEntryForKey(Objectkey){
  257. //猎取哈希值。若key为null,则哈希值为0;不然挪用hash()举行盘算
  258. inthash=(key==null)?0:hash(key.hashCode());
  259. inti=indexFor(hash,table.length);
  260. Entry<K,V>prev=table[i];
  261. Entry<K,V>e=prev;
  262. //删除链表中“键为key”的元素
  263. //实质是“删除单向链表中的节点”
  264. while(e!=null){
  265. Entry<K,V>next=e.next;
  266. Objectk;
  267. if(e.hash==hash&&
  268. ((k=e.key)==key||(key!=null&&key.equals(k)))){
  269. modCount++;
  270. size--;
  271. if(prev==e)
  272. table[i]=next;
  273. else
  274. prev.next=next;
  275. e.recordRemoval(this);
  276. returne;
  277. }
  278. prev=e;
  279. e=next;
  280. }
  281. returne;
  282. }
  283. //删除“键值对”
  284. finalEntry<K,V>removeMapping(Objecto){
  285. if(!(oinstanceofMap.Entry))
  286. returnnull;
  287. Map.Entry<K,V>entry=(Map.Entry<K,V>)o;
  288. Objectkey=entry.getKey();
  289. inthash=(key==null)?0:hash(key.hashCode());
  290. inti=indexFor(hash,table.length);
  291. Entry<K,V>prev=table[i];
  292. Entry<K,V>e=prev;
  293. //删除链表中的“键值对e”
  294. //实质是“删除单向链表中的节点”
  295. while(e!=null){
  296. Entry<K,V>next=e.next;
  297. if(e.hash==hash&&e.equals(entry)){
  298. modCount++;
  299. size--;
  300. if(prev==e)
  301. table[i]=next;
  302. else
  303. prev.next=next;
  304. e.recordRemoval(this);
  305. returne;
  306. }
  307. prev=e;
  308. e=next;
  309. }
  310. returne;
  311. }
  312. //清空HashMap,将一切的元素设为null
  313. publicvoidclear(){
  314. modCount++;
  315. Entry[]tab=table;
  316. for(inti=0;i<tab.length;i++)
  317. tab[i]=null;
  318. size=0;
  319. }
  320. //是不是包括“值为value”的元素
  321. publicbooleancontainsValue(Objectvalue){
  322. //若“value为null”,则挪用containsNullValue()查找
  323. if(value==null)
  324. returncontainsNullValue();
  325. //若“value不为null”,则查找HashMap中是不是有值为value的节点。
  326. Entry[]tab=table;
  327. for(inti=0;i<tab.length;i++)
  328. for(Entrye=tab[i];e!=null;e=e.next)
  329. if(value.equals(e.value))
  330. returntrue;
  331. returnfalse;
  332. }
  333. //是不是包括null值
  334. privatebooleancontainsNullValue(){
  335. Entry[]tab=table;
  336. for(inti=0;i<tab.length;i++)
  337. for(Entrye=tab[i];e!=null;e=e.next)
  338. if(e.value==null)
  339. returntrue;
  340. returnfalse;
  341. }
  342. //克隆一个HashMap,并前往Object对象
  343. publicObjectclone(){
  344. HashMap<K,V>result=null;
  345. try{
  346. result=(HashMap<K,V>)super.clone();
  347. }catch(CloneNotSupportedExceptione){
  348. //assertfalse;
  349. }
  350. result.table=newEntry[table.length];
  351. result.entrySet=null;
  352. result.modCount=0;
  353. result.size=0;
  354. result.init();
  355. //挪用putAllForCreate()将全体元素增加到HashMap中
  356. result.putAllForCreate(this);
  357. returnresult;
  358. }
  359. //Entry是单向链表。
  360. //它是“HashMap链式存储法”对应的链表。
  361. //它完成了Map.Entry接口,即完成getKey(),getValue(),setValue(Vvalue),equals(Objecto),hashCode()这些函数
  362. staticclassEntry<K,V>implementsMap.Entry<K,V>{
  363. finalKkey;
  364. Vvalue;
  365. //指向下一个节点
  366. Entry<K,V>next;
  367. finalinthash;
  368. //机关函数。
  369. //输出参数包含"哈希值(h)","键(k)","值(v)","下一节点(n)"
  370. Entry(inth,Kk,Vv,Entry<K,V>n){
  371. value=v;
  372. next=n;
  373. key=k;
  374. hash=h;
  375. }
  376. publicfinalKgetKey(){
  377. returnkey;
  378. }
  379. publicfinalVgetValue(){
  380. returnvalue;
  381. }
  382. publicfinalVsetValue(VnewValue){
  383. VoldValue=value;
  384. value=newValue;
  385. returnoldValue;
  386. }
  387. //判别两个Entry是不是相称
  388. //若两个Entry的“key”和“value”都相称,则前往true。
  389. //不然,前往false
  390. publicfinalbooleanequals(Objecto){
  391. if(!(oinstanceofMap.Entry))
  392. returnfalse;
  393. Map.Entrye=(Map.Entry)o;
  394. Objectk1=getKey();
  395. Objectk2=e.getKey();
  396. if(k1==k2||(k1!=null&&k1.equals(k2))){
  397. Objectv1=getValue();
  398. Objectv2=e.getValue();
  399. if(v1==v2||(v1!=null&&v1.equals(v2)))
  400. returntrue;
  401. }
  402. returnfalse;
  403. }
  404. //完成hashCode()
  405. publicfinalinthashCode(){
  406. return(key==null?0:key.hashCode())^
  407. (value==null?0:value.hashCode());
  408. }
  409. publicfinalStringtoString(){
  410. returngetKey()+"="+getValue();
  411. }
  412. //当向HashMap中增加元素时,绘挪用recordAccess()。
  413. //这里不做任那边理
  414. voidrecordAccess(HashMap<K,V>m){
  415. }
  416. //当从HashMap中删除元素时,绘挪用recordRemoval()。
  417. //这里不做任那边理
  418. voidrecordRemoval(HashMap<K,V>m){
  419. }
  420. }
  421. //新增Entry。将“key-value”拔出指定地位,bucketIndex是地位索引。
  422. voidaddEntry(inthash,Kkey,Vvalue,intbucketIndex){
  423. //保留“bucketIndex”地位的值到“e”中
  424. Entry<K,V>e=table[bucketIndex];
  425. //设置“bucketIndex”地位的元素为“新Entry”,
  426. //设置“e”为“新Entry的下一个节点”
  427. table[bucketIndex]=newEntry<K,V>(hash,key,value,e);
  428. //若HashMap的实践巨细不小于“阈值”,则调剂HashMap的巨细
  429. if(size++>=threshold)
  430. resize(2*table.length);
  431. }
  432. //创立Entry。将“key-value”拔出指定地位,bucketIndex是地位索引。
  433. //它和addEntry的区分是:
  434. //(01)addEntry()一样平常用在新增Entry大概招致“HashMap的实践容量”凌驾“阈值”的情形下。
  435. //比方,我们新建一个HashMap,然后不休经由过程put()向HashMap中增加元素;
  436. //put()是经由过程addEntry()新增Entry的。
  437. //在这类情形下,我们不晓得什么时候“HashMap的实践容量”会凌驾“阈值”;
  438. //因而,必要挪用addEntry()
  439. //(02)createEntry()一样平常用在新增Entry不会招致“HashMap的实践容量”凌驾“阈值”的情形下。
  440. //比方,我们挪用HashMap“带有Map”的机关函数,它绘将Map的全体元素增加到HashMap中;
  441. //但在增加之前,我们已盘算好“HashMap的容量和阈值”。也就是,能够断定“即便将Map中
  442. //的全体元素增加到HashMap中,都不会凌驾HashMap的阈值”。
  443. //此时,挪用createEntry()便可。
  444. voidcreateEntry(inthash,Kkey,Vvalue,intbucketIndex){
  445. //保留“bucketIndex”地位的值到“e”中
  446. Entry<K,V>e=table[bucketIndex];
  447. //设置“bucketIndex”地位的元素为“新Entry”,
  448. //设置“e”为“新Entry的下一个节点”
  449. table[bucketIndex]=newEntry<K,V>(hash,key,value,e);
  450. size++;
  451. }
  452. //HashIterator是HashMap迭代器的笼统出来的父类,完成了大众了函数。
  453. //它包括“key迭代器(KeyIterator)”、“Value迭代器(ValueIterator)”和“Entry迭代器(EntryIterator)”3个子类。
  454. privateabstractclassHashIterator<E>implementsIterator<E>{
  455. //下一个元素
  456. Entry<K,V>next;
  457. //expectedModCount用于完成fast-fail机制。
  458. intexpectedModCount;
  459. //以后索引
  460. intindex;
  461. //以后元素
  462. Entry<K,V>current;
  463. HashIterator(){
  464. expectedModCount=modCount;
  465. if(size>0){//advancetofirstentry
  466. Entry[]t=table;
  467. //将next指向table中第一个不为null的元素。
  468. //这里使用了index的初始值为0,从0入手下手顺次向后遍历,直到找到不为null的元素就加入轮回。
  469. while(index<t.length&&(next=t[index++])==null)
  470. ;
  471. }
  472. }
  473. publicfinalbooleanhasNext(){
  474. returnnext!=null;
  475. }
  476. //猎取下一个元素
  477. finalEntry<K,V>nextEntry(){
  478. if(modCount!=expectedModCount)
  479. thrownewConcurrentModificationException();
  480. Entry<K,V>e=next;
  481. if(e==null)
  482. thrownewNoSuchElementException();
  483. //注重!!!
  484. //一个Entry就是一个单向链表
  485. //若该Entry的下一个节点不为空,就将next指向下一个节点;
  486. //不然,将next指向下一个链表(也是下一个Entry)的不为null的节点。
  487. if((next=e.next)==null){
  488. Entry[]t=table;
  489. while(index<t.length&&(next=t[index++])==null)
  490. ;
  491. }
  492. current=e;
  493. returne;
  494. }
  495. //删除以后元素
  496. publicvoidremove(){
  497. if(current==null)
  498. thrownewIllegalStateException();
  499. if(modCount!=expectedModCount)
  500. thrownewConcurrentModificationException();
  501. Objectk=current.key;
  502. current=null;
  503. HashMap.this.removeEntryForKey(k);
  504. expectedModCount=modCount;
  505. }
  506. }
  507. //value的迭代器
  508. privatefinalclassValueIteratorextendsHashIterator<V>{
  509. publicVnext(){
  510. returnnextEntry().value;
  511. }
  512. }
  513. //key的迭代器
  514. privatefinalclassKeyIteratorextendsHashIterator<K>{
  515. publicKnext(){
  516. returnnextEntry().getKey();
  517. }
  518. }
  519. //Entry的迭代器
  520. privatefinalclassEntryIteratorextendsHashIterator<Map.Entry<K,V>>{
  521. publicMap.Entry<K,V>next(){
  522. returnnextEntry();
  523. }
  524. }
  525. //前往一个“key迭代器”
  526. Iterator<K>newKeyIterator(){
  527. returnnewKeyIterator();
  528. }
  529. //前往一个“value迭代器”
  530. Iterator<V>newValueIterator(){
  531. returnnewValueIterator();
  532. }
  533. //前往一个“entry迭代器”
  534. Iterator<Map.Entry<K,V>>newEntryIterator(){
  535. returnnewEntryIterator();
  536. }
  537. //HashMap的Entry对应的汇合
  538. privatetransientSet<Map.Entry<K,V>>entrySet=null;
  539. //前往“key的汇合”,实践上前往一个“KeySet对象”
  540. publicSet<K>keySet(){
  541. Set<K>ks=keySet;
  542. return(ks!=null?ks:(keySet=newKeySet()));
  543. }
  544. //Key对应的汇合
  545. //KeySet承继于AbstractSet,申明该汇合中没有反复的Key。
  546. privatefinalclassKeySetextendsAbstractSet<K>{
  547. publicIterator<K>iterator(){
  548. returnnewKeyIterator();
  549. }
  550. publicintsize(){
  551. returnsize;
  552. }
  553. publicbooleancontains(Objecto){
  554. returncontainsKey(o);
  555. }
  556. publicbooleanremove(Objecto){
  557. returnHashMap.this.removeEntryForKey(o)!=null;
  558. }
  559. publicvoidclear(){
  560. HashMap.this.clear();
  561. }
  562. }
  563. //前往“value汇合”,实践上前往的是一个Values对象
  564. publicCollection<V>values(){
  565. Collection<V>vs=values;
  566. return(vs!=null?vs:(values=newValues()));
  567. }
  568. //“value汇合”
  569. //Values承继于AbstractCollection,分歧于“KeySet承继于AbstractSet”,
  570. //Values中的元素可以反复。由于分歧的key能够指向不异的value。
  571. privatefinalclassValuesextendsAbstractCollection<V>{
  572. publicIterator<V>iterator(){
  573. returnnewValueIterator();
  574. }
  575. publicintsize(){
  576. returnsize;
  577. }
  578. publicbooleancontains(Objecto){
  579. returncontainsValue(o);
  580. }
  581. publicvoidclear(){
  582. HashMap.this.clear();
  583. }
  584. }
  585. //前往“HashMap的Entry汇合”
  586. publicSet<Map.Entry<K,V>>entrySet(){
  587. returnentrySet0();
  588. }
  589. //前往“HashMap的Entry汇合”,它实践是前往一个EntrySet对象
  590. privateSet<Map.Entry<K,V>>entrySet0(){
  591. Set<Map.Entry<K,V>>es=entrySet;
  592. returnes!=null?es:(entrySet=newEntrySet());
  593. }
  594. //EntrySet对应的汇合
  595. //EntrySet承继于AbstractSet,申明该汇合中没有反复的EntrySet。
  596. privatefinalclassEntrySetextendsAbstractSet<Map.Entry<K,V>>{
  597. publicIterator<Map.Entry<K,V>>iterator(){
  598. returnnewEntryIterator();
  599. }
  600. publicbooleancontains(Objecto){
  601. if(!(oinstanceofMap.Entry))
  602. returnfalse;
  603. Map.Entry<K,V>e=(Map.Entry<K,V>)o;
  604. Entry<K,V>candidate=getEntry(e.getKey());
  605. returncandidate!=null&&candidate.equals(e);
  606. }
  607. publicbooleanremove(Objecto){
  608. returnremoveMapping(o)!=null;
  609. }
  610. publicintsize(){
  611. returnsize;
  612. }
  613. publicvoidclear(){
  614. HashMap.this.clear();
  615. }
  616. }
  617. //java.io.Serializable的写进函数
  618. //将HashMap的“总的容量,实践容量,一切的Entry”都写进到输入流中
  619. privatevoidwriteObject(java.io.ObjectOutputStreams)
  620. throwsIOException
  621. {
  622. Iterator<Map.Entry<K,V>>i=
  623. (size>0)?entrySet0().iterator():null;
  624. //Writeoutthethreshold,loadfactor,andanyhiddenstuff
  625. s.defaultWriteObject();
  626. //Writeoutnumberofbuckets
  627. s.writeInt(table.length);
  628. //Writeoutsize(numberofMappings)
  629. s.writeInt(size);
  630. //Writeoutkeysandvalues(alternating)
  631. if(i!=null){
  632. while(i.hasNext()){
  633. Map.Entry<K,V>e=i.next();
  634. s.writeObject(e.getKey());
  635. s.writeObject(e.getValue());
  636. }
  637. }
  638. }
  639. privatestaticfinallongserialVersionUID=362498820763181265L;
  640. //java.io.Serializable的读取函数:依据写进体例读出
  641. //将HashMap的“总的容量,实践容量,一切的Entry”顺次读出
  642. privatevoidreadObject(java.io.ObjectInputStreams)
  643. throwsIOException,ClassNotFoundException
  644. {
  645. //Readinthethreshold,loadfactor,andanyhiddenstuff
  646. s.defaultReadObject();
  647. //Readinnumberofbucketsandallocatethebucketarray;
  648. intnumBuckets=s.readInt();
  649. table=newEntry[numBuckets];
  650. init();//Givesubclassachancetodoitsthing.
  651. //Readinsize(numberofMappings)
  652. intsize=s.readInt();
  653. //Readthekeysandvalues,andputthemappingsintheHashMap
  654. for(inti=0;i<size;i++){
  655. Kkey=(K)s.readObject();
  656. Vvalue=(V)s.readObject();
  657. putForCreate(key,value);
  658. }
  659. }
  660. //前往“HashMap总的容量”
  661. intcapacity(){returntable.length;}
  662. //前往“HashMap的加载因子”
  663. floatloadFactor(){returnloadFactor;}
  664. }
复制代码
申明:
<p>
他们对jsp,servlet,javabean进行封装就是为了展示他们的某个思想,与java的开发并没有必然的关系,也不见得在所以情况下,别人使用起来会简单。
精灵巫婆 该用户已被删除
沙发
发表于 2015-1-20 12:34:38 | 只看该作者
应用在电视机、电话、闹钟、烤面包机等家用电器的控制和通信。由于这些智能化家电的市场需求没有预期的高,Sun公司放弃了该项计划。随着1990年代互联网的发展
再见西城 该用户已被删除
板凳
发表于 2015-1-24 16:08:35 | 只看该作者
是一种使用者不需花费很多时间学习的语言
小妖女 该用户已被删除
地板
发表于 2015-2-2 10:02:05 | 只看该作者
关于设计模式的资料,还是向大家推荐banq的网站 [url]http://www.jdon.com/[/url],他把GOF的23种模式以通俗易懂的方式诠释出来,纯Java描述,真是经典中的经典。
只想知道 该用户已被删除
5#
发表于 2015-2-3 12:16:35 | 只看该作者
那么我书也看了,程序也做了,别人问我的问题我都能解决了,是不是就成为高手了呢?当然没那么简单,这只是万里长征走完了第一步。不信?那你出去接一个项目,你知道怎么下手吗,你知道怎么设计吗,你知道怎么组织人员进行开发吗?你现在脑子里除了一些散乱的代码之外,可能再没有别的东西了吧!
兰色精灵 该用户已被删除
6#
发表于 2015-2-8 22:01:47 | 只看该作者
Java是一个纯的面向对象的程序设计语言,它继承了 C++语言面向对象技术的核心。Java舍弃了C ++语言中容易引起错误的指针(以引用取代)、运算符重载(operator overloading)
谁可相欹 该用户已被删除
7#
发表于 2015-2-26 11:30:55 | 只看该作者
在全球云计算和移动互联网的产业环境下,Java更具备了显著优势和广阔前景。
第二个灵魂 该用户已被删除
8#
发表于 2015-3-8 14:20:00 | 只看该作者
Java 编程语言的风格十分接近C、C++语言。
9#
发表于 2015-3-16 01:10:24 | 只看该作者
你可以去承接一些项目做了,一开始可能有些困难,可是你有技术积累,又考虑周全,接下项目来可以迅速作完,相信大家以后都会来找你的,所以Money就哗啦啦的。。。。。。
因胸联盟 该用户已被删除
10#
发表于 2015-3-22 18:12:42 | 只看该作者
Sun公司看见Oak在互联网上应用的前景,于是改造了Oak,于1995年5月以Java的名称正式发布。Java伴随着互联网的迅猛发展而发展,逐渐成为重要的网络编程语言。
小女巫 该用户已被删除
11#
发表于 2015-3-22 18:12:42 | 只看该作者
不过,每次的执行编译后的字节码需要消耗一定的时间,这同时也在一定程度上降低了 Java 程序的运行效率。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-12-24 04:03

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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