简体   繁体   English

为什么我的get-method不能将分配的值返回给我的密钥?

[英]Why doesn't my get-method return the assigned value to my key?

I've been assigned the following task in my Datastructures and Algorithms course, and I have no idea why it does not work. 在我的数据结构和算法课程中,我已经分配了以下任务,但我不知道为什么它不起作用。

The task is to implement a Linked Hashtable. 任务是实现链接哈希表。 I have created two classes, one that acts as the key <-> value pair, representing an element (Entry class), and the Hashtable class that has the methods (currently only put and get), but I can't seem any of them to work. 我创建了两个类,一个用作键<->值对,表示一个元素(Entry类),以及一个Hashtable类,该类具有方法(当前仅放置和获取),但是我似乎无法他们工作。 The Hashfunction method was provided by our teachers, so I can't answer any questions regarding that. Hashfunction方法是由我们的老师提供的,因此我对此无法回答任何问题。

Whenever I execute the program, I get no errors, but the list returns empty. 每当执行程序时,都不会出现错误,但是列表将返回空。 Anyone here who can guide towards the right direction of where I am doing wrong? 在座的任何人都可以引导我正确地做错事情的正确方向? I assume the error lies within the put method, but I can't seem to figure out where to issue might be. 我认为错误在于put方法之内,但我似乎无法弄清楚可能在哪里发出。

Best regards, Victor 最好的问候,维克多

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

Class that holds all the methods for the Hashtable itself: 包含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 (for Krishas comment): 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);
                }
            }
        }
    }

What is wrong 怎么了

That is indeed because of your put method. 那确实是因为您的put方法。 Your call to setNext is in the wrong place, and this has 2 consequences: 您对setNext调用在错误的位置,这有2种后果:

  • since the list is initially empty, it.hasNext() will return false, and you will never add anything to the list 由于列表最初是空的,因此it.hasNext()将返回false,并且您将永远不会在列表中添加任何内容
  • even if you managed to add something to the list, you are calling setNext only if the first key in the list doesn't match. 即使您设法将某些内容添加到列表中,也仅在列表中的第一个键不匹配时才调用setNext So you are always discarding the second element. 因此,您始终会丢弃第二个元素。

I think some of your I clarity comes from your confusing the two kinds of lists you are handling here: one is the lists inside the table, whose purpose is to handle collisions, meaning different keys ending up in same index of table. 我认为您的一些清晰性来自您在此处处理的两种列表的混淆:一种是表内的列表,其目的是处理冲突,这意味着不同的键最终以相同的表索引结尾。 The other one is the global list, whose purpose is to record the order of insertion. 另一个是全局列表,其目的是记录插入顺序。

For the first type, you don't need 'setNext', you only need to 'add' to it. 对于第一种类型,您不需要“ setNext”,只需要将其“添加”。 SetNext is actually meant for the secon type (see below). SetNext实际上是针对secon类型的(请参见下文)。

What you should do 你应该怎么做

You should add a new entry only if after processing the whole list there is no match (which also includes the case where the list is empty), meaning after your while loop. 仅当在处理了整个列表之后没有匹配项(也包括列表为空的情况)时才应添加新条目,这意味着在while循环之后。

Other notes on your code 有关代码的其他说明

  • you can simplify your iteration on your list by using the for-each statement. 您可以使用for-each语句简化列表上的迭代。 Instead of writing 而不是写作

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

    You can write 你可以写

     for(Entry entry : list){ 
  • it seems to me that your code as it is posted doesn't compile, since you are redefining the variable entry several times. 在我看来,您发布的代码无法编译,因为您多次redefining了变量entry You should define it outside the loop, and only assign values to it in the loop. 您应该在循环之外定义它,并且仅在循环中为其分配值。

  • as mentioned by others, the equals method of your Entry class is uselessly complex. 正如其他人所提到的, Entry类的equals方法是无用的复杂。 You can replace your code by: 您可以通过以下方式替换代码:

     return key.equals(obj); 
  • you don't need your insertionOrder list. 您不需要insertionOrder列表。 The whole point of having a next field in your Entry class, is to be able to link entries so you can iterate on them based on insertion order. Entry类中具有next字段的全部目的是能够链接条目,以便您可以根据插入顺序对其进行迭代。 All you need to record is the head of the list (the first Entry as well as the tail of it (the latest inserted Entry ), so you can link from it. 您需要记录的只是列表的开头(第一个Entry以及结尾(最新插入的Entry )),因此可以从列表进行链接。

End result for your put method 您的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;
}

Your put method doesn't insert any element to the table, Because there is no element in the linkedList in the initial stage. 您的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);
        }
    }

In this code the table will be empty when you insert the first element. 在此代码中,当您插入第一个元素时,该表将为空。 so the iteration will exit without inserting anything to the table. 因此迭代将退出而无需在表中插入任何内容。 Hence get returns null. 因此,get返回null。

You can use something like this, 你可以这样使用

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

Please note this is just for the current issue, I'm not sure about your intention. 请注意,这仅是当前问题,我不确定您的意图。

You could do something like this(I commented to make it clearer): 您可以做这样的事情(我评论说得更清楚):

    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
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM