diff --git a/Hashmaps/implementation/HashMap.java b/Hashmaps/implementation/HashMap.java new file mode 100644 index 0000000..a89096c --- /dev/null +++ b/Hashmaps/implementation/HashMap.java @@ -0,0 +1,111 @@ +package implementation; + +import java.util.LinkedList; +public class HashMap { + class HashElement implements Comparable> { + K key; + V value; + + public HashElement(K key, V value) { + this.key = key; + this.value = value; + } + + public K getKey() { return key; } + + public V getValue() { return value; } + + @Override + public int compareTo(HashElement otherHashElement) { + return ((Comparable)this.key).compareTo(otherHashElement.key); + } + } + + int elementSize = 0; + int tableSize; + double maxLoadFactor; + LinkedList>[] hashtable; + + public HashMap(int tableSize) { + this.tableSize = tableSize; + this.hashtable = (LinkedList>[]) new LinkedList + [tableSize]; // Fixed array initialization + this.maxLoadFactor = 0.75; + this.elementSize = 0; + for (int i = 0; i < tableSize; i++) { + this.hashtable[i] = new LinkedList<>(); + } + } + + // associative array for fast search and removal + // one for key another for value + + // hash function is property of data + // fast, low collision + // equal return same value + public int hashCode(String s, int tableSize) { + int g = 31; + int hash = 0; + for (int i = 0; i < s.length(); i++) { + hash = g * hash + s.charAt(i); + } + // if modulo result is negative -> change the first bit + // to dissolve negative , number & 0X07FFFFFFF + return hash % tableSize; + } + + public int hashIndex(int hash) { return (hash & 0x7FFFFFFF) % tableSize; } + // to avoid collision + // odd sized or prime number table + + public boolean add(K key, V value) { + if (getLoadFactor() > maxLoadFactor) { + resize(tableSize * 2); + } + + int index = hashIndex(key.hashCode()); // index to add + if (hashtable[index] == null) { + hashtable[index] = + new LinkedList<>(); // Create a new LinkedList if it doesn't exist + } + HashElement newHash = new HashElement<>(key, value); + hashtable[index].add(newHash); + elementSize++; + return true; + } + + public double getLoadFactor() { return (double)elementSize / tableSize; } + + public void resize(int newTableSize) { + LinkedList>[] newTable = + (LinkedList>[]) new LinkedList[newTableSize]; + for (int i = 0; i < newTableSize; i++) { + newTable[i] = new LinkedList<>(); + } + + for (LinkedList> list : hashtable) { + if (list != null) { + for (HashElement element : list) { + int index = hashIndex(element.getKey().hashCode()); + newTable[index].add(element); + } + } + } + tableSize = newTableSize; + hashtable = newTable; + } + + public V getvalue(K key) { + int index = hashIndex(key.hashCode()); + LinkedList> current = hashtable[index]; + + if (current != null) { + for (var element : current) { + if (element.getKey().equals(key)) { + return element.getValue(); + } + } + } + return null; + } +} diff --git a/Hashmaps/implementation/LinkedList.java b/Hashmaps/implementation/LinkedList.java new file mode 100644 index 0000000..3fee6b4 --- /dev/null +++ b/Hashmaps/implementation/LinkedList.java @@ -0,0 +1,96 @@ +package implementation; + +public class LinkedList { + class Node { + E data; + Node next; + + public Node(E data) { + this.data = data; + next = null; + } + } + + private Node head; + private int size; + + public LinkedList() { + head = null; + size = 0; + } + + public void prepend(E data) { + Node node = new Node(data); + node.next = head; + head = node; + size++; + } + + public void removeFirst() { + if (head == null) + return; + head = head.next; + } + + public void add(E data) { + Node node = new Node(data); + if (head == null) { + head = node; + size++; + return; + } + + Node current = head; + while (current.next != null) { + current = current.next; + } + current.next = node; + size++; + } + public void removeLast() { + if (head == null) + return; + + // head == tail, removeFirst + if (head.next == null) { + removeFirst(); + return; + } + + Node current = head; + Node previous = null; + + while (current.next != null) { + previous = current; + current = current.next; + } + + previous.next = null; + size--; + } + + public void remove(E data) { + if (head == null) { + return; // List is empty + } + + if (head.data.equals(data)) { + // If the data to remove is in the head node, remove the head + removeFirst(); + return; + } + + Node current = head; + Node previous = null; + + while (current != null && !current.data.equals(data)) { + previous = current; + current = current.next; + } + + if (current != null) { + previous.next = current.next; + size--; + } + } +}