为什么我的get-method没有将指定的值返回到我的密钥?

时间:2016-09-22 11:22:37

标签: java data-structures hashtable

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

任务是实现Linked Hashtable。我创建了两个类,一个充当键< - >值对,表示一个元素(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);
                }
            }
        }
    }

3 个答案:

答案 0 :(得分:1)

有什么问题

这确实是因为你的put方法。您对setNext的来电是错误的,这有两个后果:

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

我认为你的一些清晰度来自你对这里处理的两种列表的混淆:一种是表中的列表,其目的是处理冲突,这意味着不同的键以相同的表索引结束。另一个是全局列表,其目的是记录插入顺序。

对于第一种类型,您不需要'setNext',您只需要'添加'即可。 SetNext实际上用于secon类型(见下文)。

你应该做什么

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

关于您的代码的其他说明

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

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

    你可以写

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

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

    return key.equals(obj);
    
  • 您不需要insertionOrder列表。在next类中拥有Entry字段的重点是能够链接条目,以便您可以根据插入顺序对它们进行迭代。您需要记录的只是列表的头部(第一个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;
}

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

你可以这样做(我评论说要更清楚):

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