【问题标题】:Why doesn't my get-method return the assigned value to my key?为什么我的 get 方法不将分配的值返回给我的键?
【发布时间】:2016-09-22 11:22:36
【问题描述】:

在我的数据结构和算法课程中,我被分配了以下任务,但我不知道为什么它不起作用。

任务是实现一个链接哈希表。我创建了两个类,一个作为键 值对,代表一个元素(Entry 类),另一个是具有方法的 Hashtable 类(目前只有 put 和 get),但我似乎没有他们去工作。 Hashfunction方法是我们老师提供的,所以我无法回答任何问题。

每当我执行程序时,我都没有收到任何错误,但列表返回空。这里的任何人都可以指导我做错的正确方向吗?我认为错误在于 put 方法,但我似乎无法弄清楚问题可能在哪里。

最好的问候, 维克多

 package Laboration2;

/**
 * A class that works as a container for the key and value.
 * 'Entry' will become an element in our hashtable
 *
 * @author Victor Marante
 * @version 1.0
 * @since 2016-09-22
 */
public class Entry {

    private Object key;
    private Object value;
    private Entry next;

    public Entry(Object key, Object value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public boolean equals(Object obj) {
        Entry keyToCompare = new Entry(obj, null);
        return key.equals(keyToCompare.key);
    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    public Object getKey() {
        return key;
    }

    public Entry getNext() {
        return next;
    }

    public void setNext(Entry next) {
        this.next = next;
    }
}

包含 Hashtable 本身的所有方法的类:

package Laboration2;

import javax.swing.*;
import java.util.Iterator;
import java.util.LinkedList;

/**
 * Created by Victor on 22/09/16.
 */
public class Hashtable {

    private LinkedList<Object> insertionOrder = new LinkedList<Object>();
    private LinkedList<Entry>[] table;

    // Constructor that initiates a hashtable
    public Hashtable(int size) {
        table = (LinkedList<Entry>[]) new LinkedList<?>[size];
        for (int i = 0; i < size; i++) {
            table[i] = new LinkedList<Entry>();
        }
    }

    // Hashfunction
    private int hashIndex(Object key) {
        int hashCode = key.hashCode();
        hashCode = hashCode % table.length;
        return (hashCode < 0) ? -hashCode : hashCode;
    }

    public Object get(Object key) {
        int hashIndex = hashIndex(key);
        LinkedList<Entry> entries = table[hashIndex];
        Iterator<Entry> it = entries.listIterator();
        while (it.hasNext()) {
            Entry entry = it.next();
            if (entry.equals(key)) {
                return entry.getValue();
            }
        }
        return null;
    }

    public void put(Object key, Object value) {
        int hashIndex = hashIndex(key);
        LinkedList<Entry> entries = table[hashIndex];
        Iterator<Entry> it = entries.listIterator();

        while (it.hasNext()) {
            Entry entry = it.next();
            if (entry.equals(key)) {
                entry.setValue(value);
                insertionOrder.add(value);
            } else {
                entry.setNext(new Entry(key, value));
                insertionOrder.add(value);
            }
        }
    }

    public static void main(String[] args) {

        Hashtable table = new Hashtable(15);
        table.put("hej", "hello");
        table.put("nej", "no");
        table.put("senare", "later");
        table.put("idag", "today");
        table.put("igår", "yesterday");

        table.get("hej");
    }
}

EDIT1(用于 Krishas 评论):

public void put(Object key, Object value) {
        int hashIndex = hashIndex(key);
        LinkedList<Entry> entries = table[hashIndex];
        Iterator<Entry> it = entries.listIterator();

        if (table[hashIndex] == null) {
            table[hashIndex] = new LinkedList<Entry>(key, value);

        } else {

            while (it.hasNext()) {
                Entry entry = it.next();
                if (entry.equals(key)) {
                    entry.setValue(value);
                    insertionOrder.add(value);
                } else {
                    entry.setNext(new Entry(key, value));
                    insertionOrder.add(value);
                }
            }
        }
    }

【问题讨论】:

  • 您是否调试过您的代码,并发现它的行为与您的预期不符?
  • 请注意,您的 Entry.equals 方法很奇怪 - 您通常会将一个 Entry 与另一个而不是键进行比较。 (它是不对称的。)覆盖 equals 而不覆盖 hashCode 也是不寻常的。
  • 您的equals 方法不是更容易写成return Objects.equal(obj, key); 吗? (无需创建Entry
  • 我认为您还需要覆盖 hashCode 方法。参考这个stackoverflow.com/questions/2265503/…
  • Hascode函数和Equals方法都是我们老师提供给我们的,所以我不会不了解

标签: java data-structures hashtable


【解决方案1】:

怎么了

确实是因为你的 put 方法。您对setNext 的呼叫位置错误,这会产生两个后果:

  • 由于列表最初为空,it.hasNext() 将返回 false,并且您永远不会向列表中添加任何内容
  • 即使您设法将某些内容添加到列表中,也只有在列表中的 first 键不匹配时才调用setNext。所以你总是丢弃第二个元素。

我认为你的一些清晰来自于你混淆了你在这里处理的两种列表:一种是表内的列表,其目的是处理冲突,这意味着不同的键最终会出现在表的同一个索引中。另一种是全局列表,其目的是记录插入的顺序。

对于第一种类型,你不需要'setNext',你只需要'add'它。 SetNext 实际上是用于 secon 类型的(见下文)。

你应该怎么做

只有在处理整个列表后没有匹配项时才应添加新条目(这也包括列表为空的情况),这意味着在您的 while 循环之后。

代码的其他说明

  • 您可以使用for-each 语句来简化列表中的迭代。而不是写

    Iterator<Entry> it = list.iterator();
    Entry entry;
    while(it.hasNext()){
       entry = it.next();
    

    你可以写

    for(Entry entry : list){
    
  • 在我看来,您发布的代码无法编译,因为您多次使用redefining 变量entry。您应该在循环之外定义它,并且只在循环中为其赋值。

  • 正如其他人所提到的,Entry 类的 equals 方法非常复杂。您可以通过以下方式替换您的代码:

    return key.equals(obj);
    
  • 您不需要您的insertionOrder 列表。在Entry 类中拥有next 字段的全部意义在于能够链接条目,以便您可以根据插入顺序对其进行迭代。您只需要记录列表的头部(第一个Entry 以及它的尾部(最新插入的Entry),以便您可以从中链接。

put 方法的最终结果

public void put(Object key, Object value) {
    int hashIndex = hashIndex(key);
    LinkedList<Entry> entries = table[hashIndex];

    for(Entry entry : entries) {
        if (entry.equals(key)) {
            entry.setValue(value);
            // You might want to update listTail here too
            return;
        }
    }
    Entry newEntry = new Entry(key, value);
    entries.add(newEntry);
    listTail.setNext(newEntry);
    listTail = newEntry;
}

【讨论】:

  • 我可能很愚蠢或只是筋疲力尽,但这不就是我正在做的吗?在我看来,它的工作方式是,如果键存在,则将值添加到该键,并且只添加值。如果该键不存在,请创建一个键,并将所述值添加到该列表中?
  • it.hasNext() 从一开始就为假时,您永远不会进入执行其中一个或另一个的 if-else 语句的循环。所以最后什么都做不了。
  • @Marante,这个答案解决了你的问题吗?
【解决方案2】:

你的put方法没有向表中插入任何元素,因为初始阶段linkedList中没有元素。

final int hashIndex = hashIndex(key);
    final LinkedList<Entry> entries = table[hashIndex];   //Here entries will be empty on first insert
    final Iterator<Entry> it = entries.listIterator();
while (it.hasNext()) {    // it.hasNext() will returns false, so loop exits without inserting value to the table
        final Entry entry = it.next();
        if (entry.equals(key)) {
            entry.setValue(value);
            insertionOrder.add(value);
        } else {
            entry.setNext(new Entry(key, value));
            insertionOrder.add(value);
        }
    }

在此代码中,当您插入第一个元素时,表格将为空。因此迭代将退出而不向表中插入任何内容。 因此 get 返回 null。

你可以使用这样的东西,

public void put(final Object key, final Object value) {
    final int hashIndex = hashIndex(key);
    final LinkedList<Entry> entries = table[hashIndex];
    final Iterator<Entry> it = entries.listIterator();
    //
    if (!it.hasNext()) {
        entries.add(new Entry(key, value));
    } else {

        while (it.hasNext()) {
            final Entry entry = it.next();
            if (entry.equals(key)) {
                entry.setValue(value);
                insertionOrder.add(value);
            } else {
                entry.setNext(new Entry(key, value));
                insertionOrder.add(value);
            }
        }
    }
}

请注意,这只是针对当前问题,我不确定您的意图。

【讨论】:

  • 好的,我现在看到问题了,谢谢!但是,在这种情况下如何添加条目?我已经对原始帖子进行了编辑,但它不起作用。我在这一行得到错误: table[hashIndex] = new LinkedList(key, value);
  • 再次检查 if (table[hashIndex] == null) this 不会为空,正如我之前提到的,它最初应该是一个空的 LinkedList。我不确定你的意图,如果你想向 LinkedList 添加元素,你可以写这样的东西, if (!it.hasNext()) { entries.add(new Entry(key, value)); } else { //你的 while 循环 }
【解决方案3】:

你可以做这样的事情(我评论是为了更清楚):

    public void put(Object key, Object value) {
    if (get(key) == null) { //If the key does not exist
        int hash = hashIndex(key); //Hash the key
        Entry<Object> e = new Entry<Object>(key, value); //create new Entry
        table[hash].add(e); //At the hashed index, add new entry,
        insertionOrder.add(value); //Add value to insertionOrder
    }
}

【讨论】:

    猜你喜欢
    • 2012-06-02
    • 1970-01-01
    • 2018-11-15
    • 2015-12-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-02
    • 2010-11-07
    • 1970-01-01
    相关资源
    最近更新 更多