【问题标题】:Java TreeMap implementation get and put methodsJava TreeMap 实现 get 和 put 方法
【发布时间】:2012-11-02 05:40:00
【问题描述】:

我正在编写 TreeMap 的实现,但在使用 get 和 put 方法时遇到了问题。代码如下:

public class MyTreeMap<K extends Comparable<? super K>,V> extends AbstractMap<K,V>  {


K key;
V value;
int height;
MyTreeMap<K,V> left,right;
int size;

private V get(K searchKey) {
    if(this.isEmpty())
        return null;//it needs an exception

    if(this.key.compareTo(searchKey) == 0)
        return this.value;
    else if(this.key.compareTo(searchKey) > 0)
        return this.left.get(searchKey);
    else
        return this.right.get(searchKey);
}

public V put(K key, V value) {

    if(this.containsKey(key)) {
        if(this.key.compareTo(key) == 0) {
            V temp = this.value;
            this.value = value;
            return temp;
        }

        else if(this.key.compareTo(key) < 0)
            return this.right.put(key, value);
        else if(this.key.compareTo(key) > 0)
            return this.left.put(key, value);
    }

    else {
        if(this.isLeaf() || this.isEmpty()) {
            if(this.key.compareTo(key) > 0) //this line gives NPE during tests
                this.left = new MyTreeMap(key,value,null,null);
            else
                this.right = new MyTreeMap(key,value,null,null);

               //check for balance and rebalance if needed
            this.size++;
            this.setHeight();
            return null;
        }

        else {
            if(this.key.compareTo(key) > 0)
                return this.left.put(key, value);
            else
                return this.right.put(key, value);
        }
    }
}

最疯狂的错误是 put 方法需要另一个 return 语句。多次检查代码,在我看来情况并非如此,因为有一个返回语句不需要任何布尔语句为真。

在测试 put 方法时,我得到一个 NPE。我认为我的代码存在一些非常严重的逻辑错误,因为我似乎无法弄清楚哪里出了问题。如果您能指出我正确的方向来解决这些各种错误,那将很有帮助。谢谢。

【问题讨论】:

  • 嗯,第一个if 需要针对所有情况的return 语句。
  • 如果您收到 NPE,请发布堆栈跟踪...
  • 您在哪里设置key 值? Map 具有键的事实并不意味着它具有单个 key 属性(它们有一堆并且不能存储在其中。它是树图,因为它是用树实现的地图,而不是其他的绕路。所以。这是一张地图!

标签: java recursion treemap comparable


【解决方案1】:

关于“额外”return 声明:

if(this.containsKey(key)) {
    if(this.key.compareTo(key) == 0) {
        V temp = this.value;
        this.value = value;
        return temp;
    }

    else if(this.key.compareTo(key) < 0)
        return this.right.put(key, value);
    else if(this.key.compareTo(key) > 0)
        return this.left.put(key, value);
}

您的逻辑是您正在检查 this.key.compareTo(key)&lt;0&gt;0==0,因此您已涵盖所有案例。但编译器并非如此,因为:

  1. 编译器不知道this.key.compareTo(key) 的值是否在所有三个执行中都相同。即使它具有检查方法的智能并看到它没有使用任何其他输入来获得结果(它没有),编译器也无法知道另一个线程是否正在同时更改键的值。

  2. 即使您执行int value=this.key.compareTo(key) 并稍后针对value 执行检查,编译器也不会检查连续的 if-elsif 是否涵盖所有值范围。无论如何,出于性能/并发原因,我建议您使用这种方法只调用一次compareTo

最简单的解决方法是将最后一个 else if (this.key.compareTo(key) &gt; 0) 更改为 else(您应该知道,如果执行该块是因为 if 必须为真。

【讨论】:

  • ... 由于this.key.compareTo(key) 可能是一个复杂的操作,您应该只计算一次表达式并将其存储在局部变量中。
猜你喜欢
  • 1970-01-01
  • 2015-06-22
  • 2018-10-10
  • 2010-12-19
  • 1970-01-01
  • 2022-10-16
  • 2016-11-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多