I am currently trying to implement a Hashtable collection--I have everything up and running but I ran into kind of a conceptual problem when I was trying to define a custom iterator for the table. I have an internal class called 'HashEntry' which are the actual objects stored in the array--they store the key, the value, and the status of the entry, i.e. Empty, Active, Deleted.
private class HashEntry
{
private TKey m_key;
private TValue m_value;
private EntryStatus status;
//standard constructor
public HashEntry(TKey key, TValue value)
{
m_key = key;
m_value = value;
status = EntryStatus.ACTIVE;
}
public HashEntry(TKey key, TValue value, EntryStatus i) {
m_key = key;
m_value = value;
status = i;
}
//default 'empty' constructor
public HashEntry()
{
//calls default constructor, creates placeholder entry
m_key = null;
m_value = null;
status = EntryStatus.EMPTY;
}
//equals operator override, this override just compares compares
// the objects held in the entry, so any object used with this
// implementation must hae=ve its own equals override
@Override
public boolean equals(Object obj)
{
if (obj == null) { return false; }
if (getClass() != obj.getClass()) { return false; }
final HashEntry other = (HashEntry) obj;
return (!((this.m_key == null) ? (other.m_key != null) : !this.m_key.equals(other.m_key)));
}
// override of the hashCode() function--just calls the hashCode
// function of the embedded object, so that must be provided
@Override
public int hashCode()
{
return this.m_key.hashCode();
}
// toString override just returns the toString of the embedded object
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append(m_key.toString()).append(m_value.toString());
return sb.toString();
}
}
This is the first part of my question--If I want to be able to iterate through the table, should I be iterating through (and therefore returning) HashEntry objects, or is it hashtable convention to iterate through the actual value stored in the table? The HashEntry class is private, so I assume its bad practice to return instances of it...
But if thats the case, how do I create an Hashtable iterator that iterates through its HashEntrys' objects? Do I have to define an iterator/iterable in HashEntry class?
Generally speaking, yes, it would probably be better if you did provide an iterator that iterates over
HashEntry
s, so users get both the key and value (and state) when iterating. Oftentimes the value will not make sense without the key, and vice versa.Why don't you just make the
HashEntry
class apublic static
generic inner class, and make implementation-specific stuffprivate
? You'll probably need to makeHashEntry
generic as well, because I'm assuming that your parent class (let's just call itMyHashTable
) is also generic based on theTKey
andTValue
.So, if I were you, I'd make you're
HashEntry
andMyHashTable
look more like this:Note that the
HashEntry
is an inner class ofMyHashTable
now, it's generic, and it's constructors are nowprivate
. This guarantees that nobody except that outer classMyHashTable
can instantiate aHashEntry
, because instantiating one outside of your hash table wouldn't make sense (see this). However, other people can access the keys and values of the entry through getters.The iterator itself would be an instance of
Iterator<MyHashTable.HashEntry<TKey, TValue>>
. As for writing one, that depends on your own hash table implementation, but you basically you need a way get the next element in whatever sequence:Iterator<E>.next()
.For example, here is an
iterator()
method implementation that iterates over a simple array:(source: https://stackoverflow.com/a/5849625/837703)
Hope this helped a bit.