-
Notifications
You must be signed in to change notification settings - Fork 0
Hash table test #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <module type="JAVA_MODULE" version="4"> | ||
| <component name="NewModuleRootManager" inherit-compiler-output="true"> | ||
| <exclude-output /> | ||
| <content url="file://$MODULE_DIR$"> | ||
| <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> | ||
| </content> | ||
| <orderEntry type="inheritedJdk" /> | ||
| <orderEntry type="sourceFolder" forTests="false" /> | ||
| </component> | ||
| </module> | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,150 @@ | ||
| package ru.spbau.dkaznacheev; | ||
|
|
||
| /** | ||
| * Stores elements of java.lang.String inside by their hash codes. | ||
| * Automatically resizes if the size exceeds a certain fraction of capacity. | ||
| **/ | ||
| public class HashTable { | ||
| /** | ||
| * Current number of elements in the table. | ||
| **/ | ||
| private int size; | ||
|
|
||
| /** | ||
| * Current capacity of the table. | ||
| **/ | ||
| private int capacity; | ||
|
|
||
| /** | ||
| * The storage, consists of Lists, which contain the elements. | ||
| **/ | ||
| private List storage[]; | ||
|
|
||
| /** | ||
| * The size-to-capacity ratio after which the resizing happens. | ||
| **/ | ||
| private final double SIZE_PERCENT_LIMIT = 0.75; | ||
|
|
||
| /** | ||
| * Creates a HashTable with default capacity 4. | ||
| */ | ||
| public HashTable() { | ||
| this(4); | ||
| } | ||
|
|
||
| /** | ||
| * Creates a HashTable with given capacity. | ||
| */ | ||
| public HashTable(int capacity) { | ||
| this.capacity = capacity; | ||
| storage = new List[capacity]; | ||
| for (int i = 0; i < capacity; i++) { | ||
| storage[i] = new List(); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Returns the hash code of the given string. | ||
| * @param string The string that gets hashed. | ||
| * @return The hash. | ||
| **/ | ||
| private int getHash(String string) { | ||
| int stringHash = 7; | ||
| for (int i = 0; i < string.length(); i++) { | ||
| stringHash = (stringHash * 31 + string.charAt(i)); | ||
| } | ||
| return stringHash; | ||
| } | ||
|
|
||
| /** | ||
| * Finds the position in the storage array by the key. | ||
| * @param key The given key | ||
| * @return The index in the array. | ||
| **/ | ||
| private int getIndex(String key) { | ||
| int hash = getHash(key); | ||
| return hash & (capacity - 1); | ||
| } | ||
|
|
||
| /** | ||
| * Resizes the table. | ||
| * @param newCapacity New capacity of the table. | ||
| **/ | ||
| private void resize(int newCapacity) { | ||
| HashTable newTable = new HashTable(newCapacity); | ||
| for (int i = 0; i < capacity; i++) { | ||
| while (storage[i].size() > 0) { | ||
| List.Pair pair = storage[i].popFront(); | ||
| newTable.put(pair.getKey(), pair.getValue()); | ||
| } | ||
| } | ||
| this.storage = newTable.storage; | ||
| this.capacity = newTable.capacity; | ||
| } | ||
|
|
||
| /** | ||
| * Returns how many elements is in the table. | ||
| * @return The table size. | ||
| **/ | ||
| public int size() { | ||
| return size; | ||
| } | ||
|
|
||
| /** | ||
| * Checks if there is an element with the given key in the table. | ||
| * @param key The given key. | ||
| * @return Whether there is an element. | ||
| **/ | ||
| public boolean contains(String key) { | ||
| int index = getIndex(key); | ||
| return storage[index].contains(key); | ||
| } | ||
|
|
||
| /** | ||
| * Changes or adds the value of the given key, returns the previous value. | ||
| * @param key The key | ||
| * @param value The new value | ||
| * @return Previous value, null if there was no value with this key. | ||
| **/ | ||
| public String put(String key, String value) { | ||
| int index = getIndex(key); | ||
| if (!storage[index].contains(key)) | ||
| size++; | ||
| String result = storage[index].put(key, value); | ||
| if (size >= SIZE_PERCENT_LIMIT * capacity) | ||
| resize(2 * capacity); | ||
| return result; | ||
| } | ||
|
|
||
| /** | ||
| * Returns the value stored with given key. | ||
| * @param key The key. | ||
| * @return The value stored, null if there was no value with this key. | ||
| **/ | ||
| public String get(String key) { | ||
| int index = getIndex(key); | ||
| return storage[index].get(key); | ||
| } | ||
|
|
||
| /** | ||
| * Returns the value stored with given key and removes the key-value pair from the table. | ||
| * @param key The key. | ||
| * @return The value stored, null if there was no value with this key. | ||
| **/ | ||
| public String remove(String key) { | ||
| int index = getIndex(key); | ||
| if (storage[index].contains(key)) { | ||
| size--; | ||
| } | ||
| return storage[index].remove(key); | ||
| } | ||
|
|
||
| /** | ||
| * Clears the table. | ||
| **/ | ||
| public void clear() { | ||
| for (int i = 0; i < capacity; i++) | ||
| storage[i] = new List(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Лучше у всех операторов типа if, for и т.д. заключать тело в фигурные скобки, даже если там один оператор, во избежание ошибок в духе for (int i = 0; i < capacity; i++)
System.out.println("Creating list");
storage[i] = new List(); |
||
| size = 0; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| package ru.spbau.dkaznacheev; | ||
| import org.junit.Test; | ||
|
|
||
| import static org.junit.Assert.assertTrue; | ||
| import static org.junit.Assert.assertEquals; | ||
| import static org.junit.Assert.assertNull; | ||
|
|
||
| public class HashTableTest { | ||
| @Test | ||
| public void emptyHashTableSize() throws Exception { | ||
| HashTable table = new HashTable(4); | ||
| assertEquals(0, table.size()); | ||
| } | ||
|
|
||
|
|
||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Лишняя пустая строчка :) |
||
| @Test | ||
| public void sizeChangesOnAdd() throws Exception { | ||
| HashTable table = new HashTable(4); | ||
| table.put("1", "v1"); | ||
| assertEquals(1, table.size()); | ||
| table.put("2", "v2"); | ||
| assertEquals(2, table.size()); | ||
| table.put("3", "v3"); | ||
| assertEquals(3, table.size()); | ||
| table.put("4", "v4"); | ||
| assertEquals(4, table.size()); | ||
| } | ||
|
|
||
| @Test | ||
| public void containsAdded() throws Exception { | ||
| HashTable table = new HashTable(4); | ||
| table.put("1", "v1"); | ||
| assertTrue(table.contains("1")); | ||
| assertTrue(!table.contains("2")); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тут лучше assertFalse |
||
| } | ||
|
|
||
| @Test | ||
| public void containsKey() throws Exception { | ||
| HashTable table = new HashTable(4); | ||
| table.put("1", "v1"); | ||
| assertEquals(1, table.size()); | ||
| assertTrue(table.contains("1")); | ||
| assertTrue(!table.contains("v1")); | ||
| String result = table.put("1", "v11"); | ||
| assertTrue(result.equals("v1")); | ||
| assertEquals(1, table.size()); | ||
| } | ||
|
|
||
|
|
||
| @Test | ||
| public void getAdded() throws Exception { | ||
| HashTable table = new HashTable(4); | ||
| table.put("1", "v1"); | ||
| table.put("2", "v2"); | ||
| assertTrue(table.get("1").equals("v1")); | ||
| assertTrue(table.get("2").equals("v2")); | ||
| } | ||
|
|
||
| @Test | ||
| public void getNotExisting() throws Exception { | ||
| HashTable table = new HashTable(4); | ||
| table.put("1", "v1"); | ||
| table.put("2", "v2"); | ||
| assertEquals(null, table.get("3")); | ||
| } | ||
|
|
||
| @Test | ||
| public void removeChangesSize() throws Exception { | ||
| HashTable table = new HashTable(4); | ||
| table.put("1", "v1"); | ||
| table.put("2", "v2"); | ||
| table.remove("1"); | ||
| assertEquals(1, table.size()); | ||
| table.remove("3"); | ||
| assertEquals(1, table.size()); | ||
| } | ||
|
|
||
| @Test | ||
| public void removedElements() throws Exception { | ||
| HashTable table = new HashTable(4); | ||
| table.put("1", "v1"); | ||
| table.put("2", "v2"); | ||
| String result = table.remove("1"); | ||
| assertTrue(result.equals("v1")); | ||
| assertTrue(!table.contains("1")); | ||
| assertTrue(table.contains("2")); | ||
| result = table.remove("3"); | ||
| assertNull(result); | ||
| } | ||
|
|
||
| @Test | ||
| public void clearTable() throws Exception { | ||
| HashTable table = new HashTable(4); | ||
| table.put("1", "v1"); | ||
| table.put("2", "v2"); | ||
| table.clear(); | ||
| assert(table.size() == 0); | ||
| assert(!table.contains("1")); | ||
| assert(!table.contains("2")); | ||
| } | ||
|
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Подозреваю, что capacity всегда равна storage.length, так что её в принципе можно не хранить