Skip to content

Commit

Permalink
Extract HashSet into its own class and add functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
espertus committed May 29, 2023
1 parent 90c025b commit ae49f5e
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 28 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ University. Its purpose is to:
## Classroom use

The recommended usage is:
1. Going over the implementation of [HashSet.java](src/main/java/HashExercise.java)
1. Going over the implementation of [HashSet.java](src/main/java/HashSet.java)
with students, showing them how the `hashCode()` function is used.
2. Discussing the contract for `hashCode()`, which requires `equals()` objects
to have equal hash codes. Point out that this is a legal implementation but
Expand Down
2 changes: 1 addition & 1 deletion run_autograder
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def compile():
"""
os.chdir("tmp")
result = subprocess.run(
"javac -g -encoding UTF8 -Xlint:none -d classes java/MyString.java java/HashExercise.java",
"javac -g -encoding UTF8 -Xlint:none -d classes java/MyString.java java/HashExercise.java java/HashSet.java",
shell=True,
stderr=subprocess.PIPE)
if result.returncode != 0:
Expand Down
26 changes: 0 additions & 26 deletions src/main/java/HashExercise.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,30 +73,4 @@ public static void main(String[] args) {
outputFailure("Unexpected error: " + e.getMessage());
}
}

static class HashSet<T> {
private final int capacity;
private final List<T>[] elements;
private int numCollisions;

public HashSet(int capacity) {
this.capacity = capacity;
elements = (List<T>[]) (new List[capacity]);
numCollisions = 0;
}

public void add(T value) {
int index = Math.abs(value.hashCode() % capacity);
if (elements[index] == null) {
elements[index] = new LinkedList<T>();
} else {
numCollisions++;
}
elements[index].add(value);
}

public int getNumCollisions() {
return numCollisions;
}
}
}
74 changes: 74 additions & 0 deletions src/main/java/HashSet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import java.util.*;

/**
* A simplified implementation of hash sets instrumented to count the number
* of collisions. Unlike {@link java.util.HashSet}, the capacity of this table
* never grows beyond its initial capacity.
*
* @param <T> the type of object stored in the set
*/
public class HashSet<T> {
private final int capacity;
private final List<T>[] elements;
private int numCollisions;

/**
* Constructs a hash set with the specified capacity (number of
* buckets).
*
* @param capacity the capacity
*/
public HashSet(int capacity) {
this.capacity = capacity;
elements = (List<T>[]) (new List[capacity]);
numCollisions = 0;
}

/**
* Adds the specified value to the hash set if it is not already present.
*
* @param value the value to add
*/
public void add(T value) {
if (contains(value)) {
return;
}
int index = Math.abs(value.hashCode() % capacity);
if (elements[index] == null) {
elements[index] = new LinkedList<T>();
} else {
numCollisions++;
}
elements[index].add(value);
}

/**
* Tests whether the hash set contains the specified value.
*
* @param value the value
* @return true if the value is in the set, false otherwise
*/
public boolean contains(T value) {
int index = Math.abs(value.hashCode() % capacity);
List<T> bucket = elements[index];
if (bucket == null) {
return false;
}
for (T item : bucket) {
if (item.equals(value)) {
return true;
}
}
return false;
}

/**
* Gets the number of times distinct values hashed to the same
* bucket during calls of {@link #add(Object)}.
*
* @return the number of collisions
*/
public int getNumCollisions() {
return numCollisions;
}
}

0 comments on commit ae49f5e

Please sign in to comment.