My algorithm constructs a word and looks up a value associated with the word in a TST.
private Node get(Node x, String key, int index) {
if (key.isEmpty()) {
return root;
}
if (x == null) {
return null;
}
char c = key.charAt(index);
if (c < x.val) {
return get(x.left, key, index);
} else if (c > x.val) {
return get(x.right, key, index);
} else if (index < key.length() - 1) {
return get(x.mid, key, index + 1);
} else {
return x;
}
}
Each node is constructed as such:
private class Node {
private char val;
private Node left, mid, right;
private Double selfWeight;
private double maxWeight;
/**
* Node constructor.
*/
private Node(char c) {
val = c;
maxWeight = 0.0;
selfWeight = null;
}
}
A word's maxWeight is set during construction, which is a modified version of standard construction of a TST:
private Node put(Node x, String key, Double weight, int index) {
char c = key.charAt(index);
if (x == null) {
x = new Node();
x.val = c;
}
if (c < x.val) {
x.left = put(x.left, key, weight, index);
} else if (c > x.val) {
x.right = put(x.right, key, weight, index);
} else if (index < key.length() - 1) {
x.mid = put(x.mid, key, weight, index + 1);
} else {
x.selfWeight = weight;
}
if (weight > x.maxWeight) {
x.maxWeight = weight;
}
return x;
}
When running my algorithm, if I insert, for e.g. "hello" with weight 20, and I do search on get("hello" + '\u0000'); the method will return null where as if I call get("hello") the method will return 20. Why is this?
My logic is that adding the 'null' char will not change the string, and printing out "hello" + '\u0000' confirms this. What is happening?
They're not the same string because they don't contain the same characters. Just because you can't see a character doesn't mean it's not there.
If you converted hello to unicode then what you're claiming is
0068 0065 006C 006C 006F 0000 is the same as 0068 0065 006C 006C 006F
If you need further explanation, go examine the equals method for String
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/String.java#String.equals%28java.lang.Object%29
/**
* Compares this string to the specified object. The result is {#code
* true} if and only if the argument is not {#code null} and is a {#code
* String} object that represents the same sequence of characters as this
* object.
*
* #param anObject
* The object to compare this {#code String} against
*
* #return {#code true} if the given object represents a {#code String}
* equivalent to this string, {#code false} otherwise
*
* #see #compareTo(String)
* #see #equalsIgnoreCase(String)
*/
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
Why is String + '/u0000' different than String?
Because '/u0000' (or NUL) is a valid character, not a string terminator.
A String in Java is a sequence of characters, not a sequence of characters terminated by a NUL (or zero).
(Actually, it is a bit more technically complicated than that. /u0000 is a 16-bit UTF-16 code-unit that also happens to be a Unicode code-point. A String is a sequence of 16-bit char values that may or may not be valid UTF-16 code-units and may or may not be a well-formed Unicode code-point sequence. But either way, the zero char / code-point / code-unit is NOT a string terminator.)
Is there any such thing as a truly empty char?
No. Certainly, not in Java.
Related
I don't understand in this code the hashcode() methode: how can you return an integer if there is a string... Basically you add a string next to a number but that doesn't maje it a string
also i don't understand the function equals, what is a object o and what is a o insteadof
public Imatriculation(int numeros, String word) {
this.numeros = numeros;
this.word = word;
}
public int hashCode() {
return this.word.hashCode() + this.numeros;
}
public boolean equals(Object o) {
return o instanceof Imatriculation
&& this.word.equals(((Imatriculation) o).word)
&& this.numeros == ((Imatriculation) o).numeros;
}
As was already pointed out hashcode returns an int not a string.
"o" is simply any object in java, it could be anything, so instanceof is used to check if object "o" is an Imatriculation before going on and checking the details of the object.
String#hashCode() is overriden from Object#hashCode() thus it also returns int. From the String source:
public int hashCode() { // <- it returns int!!!
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
The main purpose of hashCode() is "numerically represent" instance of a class in order to determine, which bucket of hash table it should occupy.
I want to initialize an Item Array but can't figure it out.
Here is my code.
public class HashTable<Item> {
private int m; // hash table size
private Item[] T; // hash table
HashTable(int M)
{
m = M;
T = new Item[M];
for(int i=0;i<M;i++){
Item T[i] = null;
}
}
...
...
SOLUTION
T = (Item[])new Object[M];
I think what you need is something like:
for(int i=0;i<M;i++){
T[i] = new Item(); // call some constructor here
}
You have
Item T[i] = ...
in your loop, while it should be just
T[i] = ...
So try these hints.
Also do this:
T = (Item[])new Object[M];
as Kumar suggested in his reply.
The thing is that Item is not really a type here. You need
to read how generics are actually compiled into bytecode,
and you will see what happens under the hood.
You are trying to create the array of Generic type,Please look at this post.
How to create a generic array in Java?
Assuming you created the class item you could call it like this:
public class HashTable
{
private int tableSize; // hash table size
private Item[] table; // hash table
public static void main(String[] args)
{
// where 10 is the number of nodes
Item[] myTable = createHashTable(10);
}
private static Item[] createHashTable(int size)
{
Item[] table = new Item[size];
for(int i = 0; i < table.length; i++)
{
table[i] = new Item(i);
}
}
}
However if you want to see an example of a full HashTable implementation:
/*
* HashTable.java
*
*
*/
/**
* A class that implements a hash table that employs open addressing
* using either linear probing, quadratic probing, or double hashing.
*/
public class HashTable {
/* Private inner class for an entry in the hash table */
private class Entry {
private String key;
private LLList valueList; // all of the values with this key
private boolean hasBeenRemoved; // has this entry been removed?
private Entry(String key, int value) {
this.key = key;
valueList = new LLList();
valueList.addItem(value, 0);
hasBeenRemoved = false;
}
}
// parameters for the second hash function -- see h2() below
private static final int H2_MIN = 5;
private static final int H2_DIVISOR = 11;
// possible types of probing
public static final int LINEAR = 0;
public static final int QUADRATIC = 1;
public static final int DOUBLE_HASHING = 2;
public static final int NUM_PROBE_TYPES = 3;
private Entry[] table; // the hash table itself
private int probeType = LINEAR; // the type of probing
// keeps track of how many times we perform a probe of a given length
private int[] probeLengthCount;
public HashTable(int size, int probeType) {
if (probeType >= 0 && probeType < NUM_PROBE_TYPES)
this.probeType = probeType;
else
throw new IllegalArgumentException("invalid probeType: " +
probeType);
table = new Entry[size];
probeLengthCount = new int[size + 1];
for (int i = 0; i <= size; i++)
probeLengthCount[i] = 0;
}
public HashTable(int size) {
// Call the other constructor to do the work.
this(size, LINEAR);
}
/* first hash function */
private int h1(String key) {
int h1 = key.hashCode() % table.length;
if (h1 < 0)
h1 += table.length;
return h1;
}
/* second hash function */
private int h2(String key) {
int h2 = key.hashCode() % H2_DIVISOR;
if (h2 < 0)
h2 += H2_DIVISOR;
h2 += H2_MIN;
return h2;
}
/*
* probeIncrement - returns the amount by which the current index
* should be incremented to obtain the nth element in the probe
* sequence
*/
private int probeIncrement(int n, int h2) {
if (n <= 0)
return 0;
switch (probeType) {
case LINEAR:
return 1;
case QUADRATIC:
return (2*n - 1);
case DOUBLE_HASHING:
default:
return h2;
}
}
/*
* probe - attempt to find a slot in the hash table for the specified key.
*
* If key is currently in the table, it returns the index of the entry.
* If key isn't in the table, it returns the index of the first empty cell
* in the table.
* If overflow occurs, it returns -1.
*/
private int probe(String key) {
int i = h1(key); // first hash function
int h2 = h2(key); // second hash function
int positionsChecked = 1;
// keep probing until we get an empty position or a match
while (table[i] != null && !key.equals(table[i].key)) {
if (positionsChecked == table.length) {
probeLengthCount[positionsChecked]++;
return -1;
}
i = (i + probeIncrement(positionsChecked, h2)) % table.length;
positionsChecked++;
}
probeLengthCount[positionsChecked]++;
return i;
}
/**
* insert - insert the specified (key, value) pair in the hash table
*/
public void insert(String key, int value) {
if (key == null)
throw new IllegalArgumentException("key must be non-null");
int i = h1(key);
int h2 = h2(key);
int positionsChecked = 1;
int firstRemoved = -1;
while (table[i] != null && !key.equals(table[i].key)) {
if (table[i].hasBeenRemoved && firstRemoved == -1)
firstRemoved = i;
if (positionsChecked == table.length)
break;
i = (i + probeIncrement(positionsChecked, h2)) % table.length;
positionsChecked++;
}
probeLengthCount[positionsChecked]++;
if (table[i] != null && key.equals(table[i].key))
table[i].valueList.addItem(value, 0);
else if (firstRemoved != -1)
table[firstRemoved] = new Entry(key, value);
else if (table[i] == null)
table[i] = new Entry(key, value);
else
throw new RuntimeException("overflow occurred");
}
/**
* search - search for the specified key, and return the
* associated list of values, or null if the key is not in the
* table
*/
public LLList search(String key) {
if (key == null)
throw new IllegalArgumentException("key must be non-null");
int i = probe(key);
if (i == -1 || table[i] == null)
return null;
else
return table[i].valueList;
}
/**
* remove - remove from the table the entry for the specified key
*/
public void remove(String key) {
if (key == null)
throw new IllegalArgumentException("key must be non-null");
int i = probe(key);
if (i == -1 || table[i] == null)
return;
table[i].key = null;
table[i].valueList = null;
table[i].hasBeenRemoved = true;
}
/**
* printStats - print the statistics for the table -- i.e., the
* number of keys and items, and stats for the number of times
* that probes of different lengths were performed
*/
public void printStats() {
int numProbes = 0;
int probeLengthSum = 0;
int numKeys = 0;
for (int i = 0; i < table.length; i++) {
if (table[i] != null && !table[i].hasBeenRemoved)
numKeys++;
}
System.out.println("\n" + numKeys + " keys");
System.out.println("probe-length stats:");
System.out.println("length\tcount");
for (int i = 1; i <= table.length; i++) {
if (probeLengthCount[i] != 0)
System.out.println(i + "\t" + probeLengthCount[i]);
numProbes += probeLengthCount[i];
probeLengthSum += (probeLengthCount[i] * i);
}
System.out.println("average probe length = " +
(double)probeLengthSum / numProbes);
}
}
Here is the second file for a Linked-Linked-List
/*
* LLList.java
*
*
*/
import java.util.*;
/**
* A class that implements our simple List interface using a linked list.
* The linked list includes a dummy head node that allows us to avoid
* special cases for insertion and deletion at the front of the list.
*/
public class LLList implements List {
// Inner class for a node. We use an inner class so that the LLList
// methods can access the instance variables of the nodes.
private class Node {
private Object item;
private Node next;
private Node(Object i, Node n) {
item = i;
next = n;
}
}
private Node head; // dummy head node
private int length; // # of items in the list
/**
* Constructs a LLList object for a list that is initially empty.
*/
public LLList() {
head = new Node(null, null);
length = 0;
}
/*
* getNode - private helper method that returns a reference to the
* ith node in the linked list. It assumes that the value of the
* parameter is valid.
*
* If i == -1, it returns a reference to the dummy head node.
*/
private Node getNode(int i) {
Node trav = head;
int travIndex = -1;
while (travIndex < i) {
travIndex++;
trav = trav.next;
}
return trav;
}
/** getItem - returns the item at position i in the list */
public Object getItem(int i) {
if (i < 0 || i >= length)
throw new IndexOutOfBoundsException();
Node n = getNode(i);
return n.item;
}
/**
* addItem - adds the specified item at position i in the list,
* shifting the items that are currently in positions i, i+1, i+2,
* etc. to the right by one. Always returns true, because the list
* is never full.
*
* We don't need a special case for insertion at the front of the
* list (i == 0), because getNode(0 - 1) will return the dummy
* head node, and the rest of insertion can proceed as usual.
*/
public boolean addItem(Object item, int i) {
if (i < 0 || i > length)
throw new IndexOutOfBoundsException();
Node newNode = new Node(item, null);
Node prevNode = getNode(i - 1);
newNode.next = prevNode.next;
prevNode.next = newNode;
length++;
return true;
}
/**
* removeItem - removes the item at position i in the list,
* shifting the items that are currently in positions i+1, i+2,
* etc. to the left by one. Returns a reference to the removed
* object.
*
* Here again, we don't need a special case for i == 0 (see the
* note accompanying addItem above).
*/
public Object removeItem(int i) {
if (i < 0 || i >= length)
throw new IndexOutOfBoundsException();
Node prevNode = getNode(i - 1);
Object removed = prevNode.next.item;
prevNode.next = prevNode.next.next;
length--;
return removed;
}
/** length - returns the number of items in the list */
public int length() {
return length;
}
/**
* isFull - always returns false, because the linked list can
* grow indefinitely and thus the list is never full.
*/
public boolean isFull() {
return false;
}
/**
* toString - converts the list into a String of the form
* [ item0 item1 ... ]
*/
public String toString() {
String str = "[ ";
Node trav = head.next; // skip over the dummy head node
while (trav != null) {
str += (trav.item + " ");
trav = trav.next;
}
str += "]";
return str;
}
/**
* iterator - returns an iterator for this list
*/
public ListIterator iterator() {
return new LLListIterator();
}
/*
*** private inner class for an iterator over an LLList ***
*/
private class LLListIterator implements ListIterator {
private Node nextNode; // the next node to visit
private Node lastVisitedNode; // the most recently visited node
public LLListIterator() {
nextNode = head.next;
lastVisitedNode = null;
}
/**
* hasNext - does the iterator have additional items to visit?
*/
public boolean hasNext() {
return (nextNode != null);
}
/**
* next - returns a reference to the next Object in the iteration
*/
public Object next() {
if (nextNode == null)
throw new NoSuchElementException();
Object item = nextNode.item;
lastVisitedNode = nextNode;
nextNode = nextNode.next;
return item;
}
}
}
Now I'm not sure anybody can really help me with this, since it's a pretty sizable amount of code to go through, but any help would be greatly appreciated. Here is my relevant code:
public class BTree implements Iterable<String> {
/** Left child */
BTree left;
/** Right Child */
BTree right;
/** Comparator to use for sorting */
Comparator<String> comp;
/** Parent node */
BTree parent;
/** String stored in this leaf */
String s;
/** # of iterators currently working on it */
int active = 0;
/** Size of the BTree */
int size;
public void build(Iterable<String> iter, int numStrings) {
if (this.active > 0) {
throw new ConcurrentModificationException();
}
else {
Iterator<String> itr = iter.iterator();
while (numStrings != 0 && itr.hasNext()) {
String s = itr.next();
if (!this.contains(s)) {
this.insert(s);
this.size++;
numStrings--;
}
}
}
}
/**
* Inserts the string into the given BTree
* #param str - String to insert
*/
private void insert(String str) {
if (this.s.equals("")) {
this.s = str;
}
else if (this.comp.compare(str, this.s) > 0) {
if (this.right == null) {
BTree bt = BTree.binTree(this.comp);
bt.s = str;
this.right = bt;
bt.parent = this;
}
else {
this.right.insert(str);
}
}
else if (this.comp.compare(str, this.s) < 0) {
if (this.left == null) {
BTree bt = BTree.binTree(this.comp);
bt.s = str;
this.left = bt;
bt.parent = this;
}
else {
this.left.insert(str);
}
}
}
private class BTreeIterator implements Iterator<String> {
/** Current BTree being iterated over */
BTree current;
/** How many next() calls have there been */
int count;
/** Size of the BTree */
int max;
/** Constructor for BTreeIterator
* #param current
*/
BTreeIterator(BTree current) {
this.current = current;
this.count = 0;
this.max = current.size;
active++;
}
/** Returns true if there is another string to iterate over
* #return boolean
*/
public boolean hasNext() {
if (this.count != this.max) {
return true;
}
else {
active--;
return false;
}
}
/**
* Returns the next string in the iterator
* #return String
*/
public String next() {
if (this.count == 0) {
this.count++;
current = this.current.getLeftMost();
if (this.current.s.equals("")) {
throw new NoSuchElementException();
}
return this.current.s;
}
else if (this.current.right != null) {
this.current = this.current.right.getLeftMost();
this.count++;
return this.current.s;
}
else {
BTree tree = this.current;
while (tree.parent.right == tree) {
tree = tree.parent;
}
this.current = tree.parent;
this.count++;
return this.current.s;
}
}
/** Throws an exception since we aren't removing anything from the trees
*/
public void remove() {
throw new UnsupportedOperationException();
}
}
}
}
The Exception gets thrown at the while (tree.parent.right == tree) line in the next() method of the iterator. The funny thing is, my code has worked just fine with a comparator comparing lexicographically and reverse lexicographically sorting through a file of 24000 words. It only throws the exception when using the following comparator:
class StringWithOutPrefixByLex implements Comparator<String> {
/**
* compares o1 and o2
* #param o1 first String in comparison
* #param o2 second String in comparison
* #return a negative integer, zero, or a positive integer
* as the first argument is less than, equal to, or
* greater than the second.
*/
public int compare(String o1, String o2) {
String s1, s2;
if(o1.length() > 4){
s1 = o1.substring(3);
}
else {
s1 = o1;
}
if(o2.length() > 4){
s2 = o2.substring(3);
}
else {
s2 = o2;
}
return s1.compareTo(s2);
}
}
Even weirder, it works fine with that comparator for the same file up to 199 words, but as soon as I have it build up to 200 words it breaks.
EDIT: I have determined that the Exception is due to the code trying to reference tree.parent.right while tree.parent is null, but I can't figure out WHY it's trying to do that. As far as I can tell, my code should never try to call a null tree.parent, as explained by my comment below.
Well, you do not actually show enough of your code, but, what about the root node of your BTree? What is the value of BTree.parent in the root node? null?
If the root node has a null parent, then, in this while loop, it is likely that :
while (tree.parent.right == tree) {
tree = tree.parent;
}
... will get to the root node, the tree will be set to tree.parent, which is null, and then the while loop test will fail because tree.parent.right will attempt to dereference a null pointer.
I need to analyze a text that fulfils the following problem:
Generate an output that shows a count of how many times each word occurs in the text. The report should be sorted first by word length, followed a natural sort.
I was docked points for my solution given below. Is there a better solution available? I have not used maps or any collection because we were told that extra credit will be due for those who don't use collections.
My POJO
/**
* An instance of this object represents the string that occurs in a sentence
* and the number of times it occurs in a single string.
*/
public class Word implements Comparable<Word> {
private final String word;
private int counter = 1;
public Word(String word) {
this.word = word;
}
public void incrementCounter() {
this.counter ++;
}
public String getWord() {
return word;
}
public int getCounter() {
return counter;
}
/**
* Overrides the default hashcode function.
*/
#Override
public int hashCode() {
int hashCode = 103034;
hashCode += this.word != null ? this.word.hashCode() ^ 3 : 0;
hashCode += this.counter ^ 2;
return hashCode;
}
/**
* Overrides the default equals function.
*/
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (!(obj instanceof Word)) {
return false;
}
Word otherWord = (Word) obj;
if (this.word != null && this.word.equals(otherWord.getWord())) {
return true;
}
return false;
}
#Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Word");
sb.append("{word='").append(word).append('\'');
sb.append(", counter=").append(counter);
sb.append('}');
return sb.toString();
}
/**
* The implementation checks for the order of comparison.
* The implementation first compares by presence of word string.
*
* #param w Word to be compared
* #return calculated order of comparison.
*/
#Override
public int compareTo(Word w) {
if (w == null) {
return -1;
}
if (this.word == null && w.getWord() != null) {
return 1;
}
if (this.word != null && w.getWord() == null) {
return -1;
}
return StringUtils.compareString(this.word, w.getWord());
}
}
import java.util.Comparator;
/**
* An instance of this class is responsible for comparing the instances of two word
* instances by comparing against the word string.
*/
public class WordComparator implements Comparator<Word> {
/**
* Compares two instances of words first by length of the word string and then by the
* word itself.
*
* #param firstWord first word to be compared
* #param secondWord second word to be compared
* #return negative number if the first word is less than the second word;
* positive if the first word is greater than the second word; 0 if equal.
*/
#Override
public int compare(Word firstWord, Word secondWord) {
if (firstWord == secondWord) {
return 0;
}
if (firstWord != null && secondWord == null) {
return -1;
}
if (firstWord == null && secondWord != null) {
return 1;
}
return StringUtils.compareString(firstWord.getWord(), secondWord.getWord());
}
}
Utility class.
public class StringUtils {
// Not to be instantiated.
private StringUtils() {}
/**
* Compares the string first by word length and then by string.
*
* #param first First string to be compared.
* #param second Second string to be compared
* #return integer representing the output of comparison.
*/
public static int compareString(String first, String second) {
if (first == second) {
return 0;
}
if (first == null && second != null) {
return 1;
}
if (first != null && second == null) {
return -1;
}
int wordLengthDifference = first.length() - second.length();
if (wordLengthDifference == 0) {
return first.compareTo(second);
}
return wordLengthDifference;
}
}
Main method:
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
/**
* Finds the number of occurrences of word a in given string. The implementation expects
* the input to be passed adsingle string argument.
*/
public class StringWordOccurences {
/**
* Finds the number of occurrences of a word in a string. The implementation relies
* on the following assumptions.
*
* <p>The word is passed as separate strings as in {#code "Hello" "World"} instead of
* a single string {#code "Hello World"}.
*
* #param args Arguments to be sorted by first word length and then by string.
*/
public static void main(String[] args) {
if (args == null || args.length == 0) {
System.out.println("There were no words. The count is 0");
return;
}
// Find the number of unique words and put them in an array.
Comparator<Word> wordComparator = new WordComparator();
Arrays.sort(args, new Comparator<String>() {
#Override
public int compare(String first, String second) {
return StringUtils.compareString(first, second);
}
});
Word [] words = new Word[args.length];
int numberOfUniqueWords = 0;
for (String wordAsString : args) {
Word word = new Word(wordAsString);
int index = Arrays.binarySearch(words, word, wordComparator);
if (index > -1) {
words[index].incrementCounter();
} else {
words[numberOfUniqueWords ++] = word;
}
}
Word [] filteredWords = Arrays.copyOf(words, numberOfUniqueWords);
// The display output.
for (Word word : filteredWords) {
System.out.println(word);
}
}
}
You don't need the binary searches after you have sorted your words in the desired order, because the identical words will be next to each other. Just go over all the words and compare each with the previous one. If they are equal, increment the counter. If they are not equal, you can print the results for the finished previous word right away (no need to store the results in an array). You also don't really need the Word class, you can do it with Strings.
A few points I can think of but obviously these are second guesses...
You have 3 places where there is similar logic for doing the Word compare.
Ditch the Arrays.sort, Arrays.binarySearch and Arrays.copyOf. Do the searching yourself - might be simpler
You could actually sort after you have reduced to unique values
I built a symbol table using an array list filled with an object "pairs" that are singly-linked chains and hold a word and the number of times it occurs in a text file. I need to use this for the FrequencyCounter program that counts the number of words in a file. For some reason, I'm getting this error when running the the FrequencyCounter with the HashST:
Processed 1215985 words (19 sec; 19710 msec
Exception in thread "main" java.lang.NullPointerException
at HashST.hashIndex(HashST.java:60)
at HashST.get(HashST.java:105)
at FrequencyCounter.main(FrequencyCounter.java:112)
I have an idea that there's something wrong with my HashST and its not putting the pairs in the ArrayList like I wanted it to. Any suggestions on what is wrong with the implementation would be greatly appreciated.
Here is my code and the code for the FrequencyCounter:
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.Iterator;
public class HashST<Key extends Comparable<Key>, Value> implements Iterable<Key> {
private ArrayList<Pair> chains;
private int numKeys;
private int numChains;
public class Pair
{
Key key;
Value value;
Pair(Key k, Value v)
{
key = k;
value = v;
}
Pair()
{}
Pair next;
}
/**
* Initialize an empty HashSt with a default of 64 empty chains.
*/
public HashST()
{
this(64);
}
/**
* Initialize an empty HashST with numChains emptychains.
* 387911 is a prime number about twice the number of distinct
* words in the leipzig1M.txt file.
*/
public HashST(int numChains)
{
this.numChains = numChains;
chains = new ArrayList<Pair>();
for(int i = 0; i < numChains; i++)
{
Pair p = new Pair(null, null);
chains.add(p);
}
}
/**
* compute the hash index for a key k if the number of
* chains is N
*/
private int hashIndex(Key k, int N)
{
return (k.hashCode() & 0x7fffffff) % N;
}
/**
* insert the Pair (k,v) into the appropriate chain and increment
* the number of keys counter or
* update the value for k if k is already in the hash table.
*
*/
public void put(Key k, Value v) {
int i = hashIndex(k, numChains);
Pair tmp = chains.get(i);
if(contains(k))
{
while(tmp.next != null)
{
if(tmp.key == k)
{
tmp.value = v;
return;
}
tmp = tmp.next;
}
}
else
{
Pair p = new Pair(k, v);
tmp.next = p;
numKeys ++;
}
}
/**
* return the value for key k if it is in the hash table
* or else return null if it is not.
*/
public Value get(Key k) {
int i = hashIndex(k, numChains);
Pair tmp = chains.get(i);
while(tmp.next != null)
{
if(tmp.key == k)
{
return tmp.value;
}
tmp = tmp.next;
}
return null;
}
/**
* remove the pair with key k if it is in the hash table
* otherwise no change.
*/
public void delete(Key k) {
if(contains(k))
{
return;
}
}
/**
* return true if the hash table contains a pair with key
* equal to k else return false
*/
public boolean contains(Key k) {
return (get(k) != null) ? true : false;
}
/**
* return the number of keys in the hash table
*/
public int size() {
return numKeys;
}
/**
* return a LinkedList<Key> containing the keys in the
* hash table
*/
public Iterable<Key> keys() {
LinkedList<Key> l = new LinkedList<Key>();
for(Pair p : chains)
{
while(p.next != null)
{
l.add(p.key);
p = p.next;
}
}
return l;
}
/**
* return an Iterator<Key> for the keys in the hash table
*/
public Iterator<Key> iterator() {
return keys().iterator();
}
}
And here is the Frequency Counter: http://algs4.cs.princeton.edu/31elementary/FrequencyCounter.java.html
According to your stack trace this would seem to be the line that threw a null pointer:
return (k.hashCode() & 0x7fffffff) % N;
So we have one object reference k, an integer constant, and a primitive N. Neither the constant nor the primitive can be null, the only thing being dereferenced here is k. So it looks like someone tried to get a value for a null k!