2012-04-19 11 views
1

現在、私はJavaでMapクラスを作成している課題に取り組んでいますが、修正することができない「put」メソッドを使用している間にエラーが発生しました。基本的に、テストが実行されると、マップ内の新しいノードは作成されません。その理由を把握できないようです。前もって感謝します!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; 
    } 
} 
} 

テスト:あなたのput(K key, V value, MapNode ref)メソッド内

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

どのような地図ですか?バイナリツリーのようなもの? –

+0

デバッガでコードをステップ実行すると、何が表示されますか? –

+0

はい、それぞれの場所にKeyとValueの両方を格納するバイナリツリーです。 – Weasler

答えて

2

、あなたが追加したいノードを含むrefに新しいMapNodeを割り当てます。

rootを渡してこのメ​​ソッドを呼び出すとわかります。これはrootに格納されたものと同じ参照をrefに格納します。これは、rootがnullでない場合、同じObjectを指すことを意味します。ただし、rootnullなので、両方ともnullを指しています。

ref = new MapNode(key, value);を割り当てると、refが新しいノードに向いていますが、rootはまだnullを指しています。

rootを新しいMapNodeに指し示す必要があります。refはそれがあなたのためではありません。

+0

ありがとう、私ができるならあなたに投票する;非常に簡潔に説明した! – Weasler

0

問題は、どこにでもルートを変更しないため、マップには何も含まれないということです。参照渡しではなく値渡しであるため、ref = new MapNode()は、呼び出し元の値ではなくローカル変数を変更します。

0

あなたの問題は、Javaが参照渡しではなく、参照渡しが値渡しであるという事実の記録を失っていることです。 ref = new MapNode(...)と言うと、実際には何も変更されていません。親ノードが新しく作成されたノードを指し示すように明示的にする必要があります。