Gettysburg College

CS 216
Data Structures and Algorithms

Spring 2026

Assignment 4

Due: Mon, Feb 16, by 11:59pm
  • method stubs:
    • CHashMap.java / .log
    • LHashMap.java / .log
    • Entry.java / .log
    • with working constructors and toString for the above classes

  • coverage-CHashMap.pdf
  • coverage-CHashMap.pdf

  • api.pdf only for CHashMap

  • junit tests: CHashMapTest.java/.log and LHashMapTest.java/.log
    • testers confirm that constructors and toString work for empty maps (i.e. as soon as created)
    • use class MyString (see Section Testing at bottom)
    • make sure to read the whole Section Testing at the bottom before writing the JUnit tests
Due: Thu, Feb 19, by 11:59pm
  • CHashMap.java / .log
  • LHashMap.java / .log
  • Entry.java / .log
  • CHashMapTest.java / .log
  • LHashMapTest.java / .log
  • coverage-CHashMap.pdf
  • coverage-LHashMap.pdf

Preliminaries

Create two separate projects CHashMap and LHashMap. These will have the files mentioned above. The Entry class is the same for both, so you can copy from one project to the other.

The CHashMap may be easier to start with.

Description

In this assignment you will implement the HashMap data structure. The HashMap can be viewed as a generalization of the primitive array or ArrayList. We still use indices to store data in the HashMap, but here the indices do not need to be sequential, and in fact, the indices do not need to be integers.

For a detailed explanation see the handout on Moodle and the example here:

Hash Map Example

Quick summary:

Inserting in a HashMap
Calculate the bucket index i where the item would have been inserted: Searching in a HashMap
Calculate the bucket index i where the item would have been inserted: Deleting from a HashMap
Calculate the bucket index i where the item would have been inserted:

Testing

See Section "Testing" at the very bottom.

Implementation

Create two separate projects called CHashMap and LHashMap that implement the methods given below using the Chaining and Linear Probing collision resolution schemes:

Keep in mind that you will need to:

The Entry Class

This class has only two data members (key and value) that can be accessed directly. This class is loosely an analog of Node for LinkedList.

For this assignment Entry will be an external class, i.e. in its own file. It is a generic class on two types <K, V> (for comparison, the LinkedList was generic on only one type <E>). Since the class is external, when used it needs to be written as Entry<K, V>, i.e. with explicit generic type K and V, unlike Node which was internal, so the generic type E was implicit and was not written.

The Entry class has method toString that returns the contents in this format:

cat:4

assuming the entry has key "cat" and value "4".

The Map Methods

Setup

Use a primitive array for the buckets:

data member sectionconstructor
LHashMap
Entry<K, V>[] _array-name_;
_array-name_ = (Entry<K, V>[]) new Entry[ ... ];
CHashMap
LinkedList<Entry<K, V>>[] _array-name_;
_array-name_ = (LinkedList<Entry<K, V>>[]) new LinkedList[ ... ];
  • Each map needs to have a data member to keep track of the size (i.e. number of entries)

  • LHashMap needs to have two Entry data members to represent the Empty and Deleted buckets; this is similar to the dummy node in the LinkedList, but now the "dummies" are data members

  • use enhanced for-loop wherever possible

  • none of the methods throw exceptions; instead they return null to indicate "failure"
?HashMap(int initialCapacity, double loadFactor)

Creates a map with the given capacity and load factor; make sure to put empty buckets in the hash map container (empty lists for Chaining, Empty marker for Linear Probing).

The loadFactor is a number in [0..1]. Initially, just assign it and ignore it.

V put(K key, V value)

Puts the given value under the given key and returns the old value associated with this key. (For LHashMap puts the entry in first D bucket.)

For LHashMap you may assume that there is always one empty bucket, so loop is guaranteed to stop; consider using while loop for LHashMap.

V get(K key)

Returns the value associated with the given key.
V remove(K key)

Removes/deletes the entry with the given key from the map and returns the entry's value.
boolean containsValue(V value)

Determines if the map contains the given value.

For LHashMap implement this using the iterator over the values in the map. This method will indirectly test the iterator. Use enhanced for loop.

void rehash()

(private, LHashMap only) Expands the map storage (after adding new entry) if size ≥ load_factor * capacity. Rehashes all the key/value pairs (cannot simply copy the entries to the same indices indices).

The effect of rehashing is to double the map capacity (twice as many buckets) and to rearrange the entries, as if someone collected all entries in left-to-right, top-to-bottom order and put them in an initially empty map.

String toString()

These should be short methods. No StringBuilder and no nested loops. Use method trim() andreplaceAll()

Returns a string representation of the map. Here are examples of maps with capacity 10 -- one map has 4 entries and the other map is empty, i.e. it has no entries, but it does have buckets:

  • for LHashMap returns (letter E is placed for Empty marker, letter D for Deleted marker)

    4:[D E 76544632:mickey 14742300:donald D 67587658:minnie E E D 22571632:tom]
    0:[E E E E E E] (for empty map)

  • for CHashMap returns:

    4:[[] [] [] [] [76544632:mickey 14742300:donald 67587658:minnie] [] [] [22571632:tom] [] []]
    0:[[] [] [] [] [] [] [] [] [] []] (for empty map)

  • the first number is the size of the map, i.e. number of entries, not number of buckets

  • in CHashMapTest and LHashMapTest, respectively, create an empty map of n buckets and assert that you got the correct string

  • avoid if statements and only one loop is needed in each case, since LinkedList and Entry have method toString, so you can simply write:

    LHashMap:      str = str + entry

    CHashMap:      str = str + list_of_entries

    in CHashMap there will be commas, so to remove at the end write:

    str = str.replaceAll(",", "")

Iterator<V> iterator()

Returns an iterator over the values stored in this map from the first bucket to the last; operation remove is not implemented.

You are only expected to implement iterator for LHashMap class. This will be similar to the Stack iterator, but hasNext() will have a loop.

Include test cases for the failing condition(s) of the iterator (recreate the map for different types of conditions.).

Testing

For testing: