我的数据结构和算法课程中已经分配了以下任务,我不知道它为什么不起作用。
任务是实现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);
}
}
}
}
答案 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
}
}