2012-04-19 70 views
1

我目前正在做一個任務,讓我創建一個Java類的Map類,並且在使用'put'方法時遇到了一個錯誤,而我似乎無法解決這個問題。實質上,當測試運行時,Map中的新節點將不會被創建,我似乎無法弄清楚原因。先謝謝你!在Java中實現一個地圖

類:

public class MyMap<K extends Comparable<K>, V> { 
private class MapNode { 
    private K key; 
    private V value; 
    private MapNode left; 
    private MapNode right; 

    public MapNode(K theKey, V theValue) { 
     key = theKey; 
     value = theValue; 
     left = null; 
     right = null; 
    } 
} 

private MapNode root; 

public MyMap() { 
    root = null; 
} 

/** 
* Associates key to value and stores mapping If key exists, replaces value 
* with a new value 
* 
* @param key 
* @param value 
* @return value replaced; null if no value 
*/ 

public V put(K key, V value) { 
    return put(key, value, root); 
} 

private V put(K key, V value, MapNode ref) { 
    V temp; 
    if (ref == null) { 
     ref = new MapNode(key, value); 
     return null; 
    } else { 
     if (ref.key.compareTo(key) == 0) { 
      temp = ref.value; 
      ref.value = value; 
      return temp; 
     } else if (key.compareTo(ref.key) < 0) 
      return put(key, value, ref.left); 
     else 
      return put(key, value, ref.right); 
    } 
} 

/** 
* Return value to which key is mapped 
* 
* @param key 
* @return value of key; null 
*/ 

public V get(K key) { 
    return get(key, root); 
} 

private V get(K key, MapNode ref) { 
    if (ref == null) { 
     return null; 
    } else { 
     if (ref.key.compareTo(key) == 0) 
      return ref.value; 
     else if (key.compareTo(ref.key) < 0) 
      return get(key, ref.left); 
     else if (key.compareTo(ref.key) > 0) 
      return get(key, ref.right); 
     else 
      return null; 
    } 
} 

/** 
* Returns true if Map already uses the key 
* 
* @param key 
* @return true; false 
*/ 

public boolean containsKey(K key) { 
    return containsKey(key, root); 
} 

private boolean containsKey(K key, MapNode ref) { 
    if (ref == null) { 
     return false; 
    } else { 
     if (ref.key.compareTo(key) == 0) 
      return true; 
     else if (key.compareTo(ref.key) < 0) 
      return containsKey(key, ref.left); 
     else if (key.compareTo(ref.key) > 0) 
      return containsKey(key, ref.right); 
     else 
      return false; 
    } 
} 
} 

測試:

import org.junit.Test; 

import static org.junit.Assert.assertEquals; 
import static org.junit.Assert.assertFalse; 
import static org.junit.Assert.assertTrue; 

public class MyMapTest { 
@Test 
public void testMyMap(){ 
    MyMap<String, Integer> m = new MyMap<String, Integer>(); 

    assertFalse(m.containsKey("one")); 
    assertEquals(null, m.get("one")); 
    assertEquals(null, m.put("one", 1)); 
    assertTrue(m.containsKey("one")); 
} 
} 
+0

這是什麼樣的地圖?某種二叉樹? – 2012-04-19 20:13:51

+0

當您在調試器中逐步完成代碼時,您會看到什麼? – 2012-04-19 20:15:54

+0

是的,在每個位置都存儲密鑰和值的二叉樹。 – Weasler 2012-04-19 20:16:03

回答

2

裏面你put(K key, V value, MapNode ref)方法,你分配一個新的MapNode到ref包含您要添加的節點。

我看到你通過傳遞root來調用該方法。這存儲與存儲在,ref中相同的參考。這意味着什麼,如果root不是null,他們會指向相同的對象。但是,由於rootnull,它們都指向null

當您指定ref = new MapNode(key, value);時,您將ref指向新節點,但root仍指向空。

你需要指向root到新的MapNode,指向ref它不會爲你做。

+0

非常感謝你,如果可以的話,我會給你投票;非常簡潔並且很好的解釋! – Weasler 2012-04-19 20:19:35

0

您遇到的問題是您不會在任何地方更改根目錄,因此您的地圖中不會有任何內容。你通過價值傳遞,而不是通過引用,所以當你做ref = new MapNode()這改變你本地變量,而不是調用者值。

0

你的問題是,你正在失去Java不是通過引用傳遞的事實 - 它通過值傳遞引用。當你說ref = new MapNode(...)時,你實際上並沒有改變任何東西。您需要明確地將父節點指向新創建的節點。