«August 2025»
12
3456789
10111213141516
17181920212223
24252627282930
31


公告
欢迎大家访问,希望大家多多交流!
    Email:hello105@ustc.edu
    QQ: 7779112
    

我的分类(专题)

首页(63)
Xml收藏(3)
Java收藏(17)
心情(11)
其他(32)


最新日志
DataStage 开发中遇到的几个问题
Tar的详细用法(转自Linux伊甸园)
UNIX常用命令-目录及文件操作命令(z
The 38 Subsystems of
DataStage安装
回来了!
rpm使用
学校好冷清阿
科大怪谈(1)
科大怪谈(2)

最新回复
回复:DataStage 开发中遇到的几
回复:DataStage 开发中遇到的几
回复:发放WALLOP邀请
回复:发放WALLOP邀请
回复:发放WALLOP邀请
回复:发放WALLOP邀请
回复:发放WALLOP邀请
回复:发放WALLOP邀请
回复:发放WALLOP邀请
回复:发放WALLOP邀请

留言板
签写新留言

为什么?
回学校了
关于wallop

统计
blog名称:hello105
日志总数:63
评论数量:174
留言数量:3
访问次数:396038
建立时间:2004年11月8日

链接

Lost Ferry

 




W3CHINA Blog首页    管理页面    写新日志    退出

[Java收藏]Java编程思想读书笔记-4(第9章-2HashMap的工作原理及其实现)(zz)
音乐昆虫 发表于 2004/12/6 22:22:20

4.    自己实现一个简单的HashMap及其原理 4.1    在put()方法中: 1)    首先通过key得出要插入的key-value pair的hash code,并这个hash code作为索引在数组bucket中找出key所对应的元素。 2)    把要插入的key-value pair封装成实现了Map.Entry接口的类的一个对象。 3)    在操作1)所找出的数组元素(也是一个LinkedList)中查看是否有与要插入的key- value pair的key相同的元素,如果有,则对之进行更新;如果无,则把要插入的key-value pair数组元素中。 4.2    在get()方法中 1)    首先通过key得出要查找的key-value pair的hash code,并这个hash code作为索引在数组bucket中找出key所对应的元素。 2)    把要查找的key-value pair的key封装成实现了Map.Entry接口的类的一个对象。 3)    在操作1)所找出的数组元素(也是一个LinkedList)中查看是否有与要插入的key-value pair的key相同的元素,如果有,则返回key所对应的value;如果无,则返回一个null。 4.3    一个实例 import java.util.*; /**  * MPair类实现了Map.Entry  */ class MPair     implements Map.Entry, Comparable{     Object key, value;     MPair(Object k, Object v){         key = k;         value = v;     }     public Object getKey() { return key; }     public Object getValue() { return value; }     public Object setValue(Object v){         Object result = value;         value = v;         return result; }                 /**                    *  当比较两个MPair对象时,比较的是它们的key值                   */     public boolean equals(Object o){         return key.equals(((MPair)o).key);     }     public int compareTo(Object rv){         return (((Comparable)key).compareTo(((MPair)rv).key));     } } class SimpleHashMap extends AbstractMap{     private final static int SZ = 997;     private LinkedList[] bucket = new LinkedList[SZ];     /**      * 把key和value封装成Map.Entry的实现类后插入到array中      */     public Object put(Object key, Object value){         Object result = null;         //通过key得到要插入的key-value pair的hash code         int index = key.hashCode() % SZ;         if(index < 0) index = - index;         if(bucket[index] == null)             bucket[index] = new LinkedList();         //通过hash code找出要插入的key所对应的array中的元素         LinkedList pairs = bucket[index];         //把要插入的key-value pair封装成MPair         MPair pair = new MPair(key, value);         ListIterator it = pairs.listIterator();         boolean found = false;      //检查是否有与要插入的key相同的key存在,如果有,就对之进行更新         while(it.hasNext()){             Object iPair = it.next();             if(iPair.equals(iPair)){                 result = ((MPair)iPair).getValue();                 it.set(pair);                 found = true;                 break;             }         }         //如果无,则把新的key-value pair插入         if(!found)             bucket[index].add(pair);         return result;     }     public Object get(Object key){         int index = key.hashCode() % SZ;         if(index < 0) index = -index;         if(bucket[index] == null) return null;         LinkedList pairs = bucket[index];         ListIterator it = pairs.listIterator();         MPair match = new MPair(key, null);         while(it.hasNext()){             Object iPair = it.next();             if(iPair.equals(match))                 return ((MPair)iPair).getValue();                         }         return null;     }     public Set entrySet(){         Set entries = new HashSet();         for(int i=0; i<bucket.length; i++){             if(bucket[i] == null) continue;             Iterator it = bucket[i].iterator();             while(it.hasNext())                 entries.add(it.next());         }         return entries;     } } public class ExplicitStatic{             public static void main(String[] args){             SimpleHashMap m = new SimpleHashMap();         for( int i=1; i<10; i++)             m.put("km" + i, "m" + i);         System.out.println(m);     } } 四.    HashMap的一些其它讨论 1.    关于HashMap中的key值的使用 1.1.    以Java的库函数做为HashMap的key值时,可以直接使用。 import java.util.*; class Counter{     int i = 1;     public String toString(){         return Integer.toString(i);     } } public class ExplicitStatic{        public static void main(String[] args){         HashMap hm = new HashMap();         for(int i = 0; i < 10000; i++)         {             //HashMap的key的类型为Integer             Integer r = new Integer((int) (Math.random() * 20));             if(hm.containsKey(r))                 ((Counter)hm.get(r)).i++;             else                 hm.put(r, new Counter());         }         System.out.println(hm);     } } 1.2.    如果在HashMap中使用你自己撰写的classes做为key,你一定得同时覆写hashCode()和equals()。 下面代码用自己实现的class做为key,但没有覆写hashCode()和equals()。 import java.util.*; class Groundhog{             int ghNumber;             Groundhog(int n) { ghNumber = n; }             public String toString(){                 return "Groundhog@" + ghNumber;             } } class Prediction{             boolean shadow = Math.random() > 0.5;             public String toString(){                 if(shadow)                     return "Six more weeks of Winter!\n";                 else                     return "Early Spring!\n";             } }         public class Test{                public static void main(String[] args){                 HashMap hm = new HashMap();                 for(int i = 1; i < 10; i++)                     hm.put(new Groundhog(i), new Prediction());                 System.out.println("hm = " + hm);                 System.out.println("Looking up prediction for Groundhog #3:");                 Groundhog gh = new Groundhog(3);                 if(hm.containsKey(gh))  //(1)                     System.out.println((Prediction)hm.get(gh));                  else                     System.out.println("Key not found: " + gh);             } } 运行结果: hm = {Groundhog@9=Early Spring! , Groundhog@8=Six more weeks of Winter! , Groundhog@7=Six more weeks of Winter! , Groundhog@6=Early Spring! , Groundhog@5=Early Spring! , Groundhog@4=Early Spring! , Groundhog@3=Early Spring! , Groundhog@2=Early Spring! , Groundhog@1=Six more weeks of Winter! } Looking up prediction for Groundhog #3: Key not found: Groundhog@3 key 没覆写hashCode()和equals(),那么在通过key取得hash code时,就会取得key的内存地址;同样,当通过equals()函 数比较两个key是否相等时,比较的也是两个key的地址。所以(1)处代码比较的结果为false(因为两个对象的内存地址肯定是不相同的)。显然,这 不是我们要得到的结果。 为了要得到正确的结果,我们只需在作为key的类中实现hashCode()和equals()。 java.util.*; class Groundhog2{             int ghNumber;             Groundhog2(int n) { ghNumber = n; }             public String toString(){                 return "Groundhog2@" + ghNumber;             }             /**          * 以ghNumber作为hash code          */             public int hashCode() { return ghNumber; }             /**          *比较的是两个key的ghNumber值          */             public boolean equals(Object o)             {                 return (o instanceof Groundhog2)                      && (ghNumber == ((Groundhog2)o).ghNumber);             } } class Prediction{             boolean shadow = Math.random() > 0.5;             public String toString(){                 if(shadow)                     return "Six more weeks of Winter!\n";                 else                     return "Early Spring!\n";             } } public class Test{                public static void main(String[] args){                 HashMap hm = new HashMap();                 for(int i = 1; i < 10; i++)                     hm.put(new Groundhog2(i), new Prediction());                 System.out.println("size = " + hm.size() + " , hm = " + hm);                 System.out.println("Looking up prediction for Groundhog #3:");                 Groundhog2 gh = new Groundhog2(2);                 if(hm.containsKey(gh))                     System.out.println((Prediction)hm.get(gh));                 else                     System.out.println("Key not found: " + gh);             } } 运行结果为: hm = {Groundhog2@9=Early Spring! , Groundhog2@8=Six more weeks of Winter! , Groundhog2@7=Six more weeks of Winter! , Groundhog2@6=Six more weeks of Winter! , Groundhog2@5=Early Spring! , Groundhog2@4=Early Spring! , Groundhog2@3=Six more weeks of Winter! , Groundhog2@2=Early Spring! , Groundhog2@1=Early Spring! } Looking up prediction for Groundhog #3: Early Spring! 在新的代码中,我们在作为key的类中实现了hashCode()和equals()函数,得到了想要的结果。 2.    HashMap的效能因子 Capacity:容量,表格中的buckets数量 Initial capacity:初始容量,表格建立之初的buckets数量。 HashMap和HashSet:各有构造函数,允许指定初始容量。 Size:大小,表格内目前所有的条目。 Load factor: 负载因子,size / capacity(大小/容量)。负载因子为0,表示一个空表格,0.5是一个半满表格,依此类推。一个轻负载表格出现碰撞 (collisions)的机会比较低,比较适合安插和查找(但会降低“通过迭代器巡访”的速度)。在HashMap和HashSet各有构造函数中指定 了负载因子后,当容器达到这个负载因子,容器的容量(buckets个数)就会自动扩充,并将原有的对象重新导入到新的buckets内(这称为 rechashing)。HashMap缺省的负载因子值是0.75。

阅读全文(2106) | 回复(0) | 编辑 | 精华


发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)
站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.031 second(s), page refreshed 144768151 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号