用Java实现Map

时间:2012-04-19 20:12:34

标签: java variable-assignment

我正在进行一项让我在Java中创建Map类的任务,并且在处理我似乎无法修复的'put'方法时遇到了错误。本质上,当测试运行时,Map中的新节点将不会被创建,我似乎无法弄清楚原因。提前谢谢!

类别:

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

3 个答案:

答案 0 :(得分:2)

put(K key, V value, MapNode ref)方法中,您将新的MapNode分配给包含您要添加的节点的ref

我看到您通过传递root来调用该方法。这会存储与<{1}}中root中存储的相同的引用。这意味着,如果ref不为null,它们将指向同一个对象。但是,由于rootroot,它们都指向null

分配null时,您将ref = new MapNode(key, value);指向新节点,但ref仍指向空。

您需要将root指向新的MapNode,将root指向它不会为您执行此操作。

答案 1 :(得分:0)

您遇到的问题是您没有在任何地方更改根,因此您的地图中不会包含任何内容。您是通过值传递的,而不是通过引用传递的,因此当您执行ref = new MapNode()时,这会更改本地变量,而不是调用者值。

答案 2 :(得分:0)

你的问题是你忘记了Java不是通过引用传递的事实 - 它通过值传递引用。当你说ref = new MapNode(...)时,你实际上并没有改变任何东西。您需要明确地使父节点指向新创建的节点。