Java程式設計思想(2nd)學習筆記(9)-2 (轉)

gugu99發表於2007-08-17
Java程式設計思想(2nd)學習筆記(9)-2 (轉)[@more@]

一.  HashMap的工作原理及實現

1.  如何實現一個Map

1.1  與Map相關的知識

1.1.1  Map.Entry介面

一個實現了Map.Entry介面的類代表的是一個Map中的條目(一個key-value pair)。所以一個Map中必須要有一個實現了Map.Entry介面的類,並用這個類來存放Map中的key-value pair。

1.1.2  public abstract Set entrySet()

1)  entrySet()函式返回一個Set,並且Set中的每一個元素都是一個Map.Entry型別的。在entrySet()函式中要把Map中所有的key-value pair以Map.Entry封裝後存入Set中的。

2)  當對Map進行修改操作後,entrySet()函式都會被。所以對Map的修改也會產生對這個Set的修改。

3)  當用這個Set的iterator進行操作時,不能進行add和addAll的操作。

1.2  實現一個簡單的Map的例項

import .util.*;

/**:namespace prefix = o ns = "urn:schemas--com::office" />

 * MPair類實現了Map.Entry

 */

class MPair

  implements Map.Entry, Comparable{

  key, value; //key和value分別用來存放Map中的key和value

  MPair(Object k, Object v){

  key = k;

  value = v;

}

//下面方法實現了Map.Entry介面中的方法

  public Object getKey() { return key; }

  public Object getValue() { return value; }

  public Object setValue(Object v){

  Object result = value;

  value = v;

  return result;

}

//下面方法實現了Comparable介面中的方法

  public boolean equals(Object o){

  return key.equals(((MPair)o).key);

  }

  public int compareTo(Object rv){

  return ((Comparable)key).compareTo(((MPair)rv).key);

  }

}

class SlowMap extends AbstractMap{

  private ArrayList

  keys = new ArrayList(),

  values = new ArrayList();

  public Object put(Object key, Object value){

  Object result = get(key);

  if(!keys.contains(key)){ //(1

  keys.add(key);

  values.add(value);

  }

  else

  values.set(keys.indexOf(key), value);

  return result;

  }

  public Object get(Object key){

  if(!keys.contains(key)){

  return null;

  }

  else

  return values.get(keys.indexOf(key));

}

//用Mpair封裝Map中的key-value pair並存入Set中

  public Set entrySet(){

  Set entries = new HashSet();

  Iterator

  ki = keys.iterator(),

  vi = values.iterator();

  while(ki.hasNext())

  entries.add(new MPair(ki.next(), vi.next()));

  return entries;

  }

}

public class ExplicitStatic{ 

  public static void main(String[] args){

  SlowMap m = new SlowMap();

  for( int i=1; i<10; i++)

  m.put("km" + i, "m" + i);

  System.out.println(m); 

  }

}

  在上面程式碼的(1)處,我們要從ArrayList中查詢出是否具有key值,而這個查詢過程線性查詢,且key不具任何順序,所以速度會很慢。

1.3  如何對Map用迭代器進行操作

其它容器可以透過iterator()函式來生成物件的迭代器,但Map是不能生成的。如果要用迭代器對Map進行操作,則要透過entrySet()函式。用entrySet()函式生成的迭代器不能對Map進行add和addAll的操作。

  public class ExplicitStatic{ 

  public static void main(String[] args){ 

  HashMap m = new HashMap();

  for( int i=1; i<10; i++)

  m.put("km" + i, "m" + i);

  System.out.println("User for l:");

  for( int i=1; i<=m.size(); i++ )

  System.out.println("km" + i + " = " + m.get("km" + i));

  System.out.println("User Iterator loop:");

  Iterator it = m.entrySet().iterator();

  while(it.hasNext()){

  Map.Entry entry = (Map.Entry)it.next();

  System.out.println(entry.getKey() + " = " + entry.getValue());

  }

  }

}

2.  與HashMap相關的幾個函式

1)  hashCode()函式

Object.hashCode()函式會為物件產生hash code。如果一個類沒有實現hashCode()函式,那麼在預設情況下將返回它的物件的地址。

2)  equals()函式

Object.equals()在比較兩個物件時,比較的是兩個物件的記憶體地址。

3.  HashMap的工作原理

3.1  用array來表現key的資訊。每個key的hashCode()函式會為key產生一個hash code,而key的hash  code作為array的。如假設有一個名為bucket的arrsy,姥一個hash code為2的key就被索引到bucket[2],key所對應的值也在bucket[2]中。

3.1  由於array中存放的是value值,而HashMap的元素個數可以是無限的,所以array中的元素指向的不是某個key的value,而是指向具有相同的hash code的key的value值(也就是說指向的是一串values值)。如假設array被定義為LinkedList []bucket = new LinkedList[10],那麼bucket[2]中存放的是所有hash code值為2的key的value。

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

  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);

  }

}


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-963763/,如需轉載,請註明出處,否則將追究法律責任。

相關文章