mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-07 01:35:16 +08:00
Add generic hashmaps (#3195)
This commit is contained in:
@ -0,0 +1,125 @@
|
|||||||
|
package com.thealgorithms.datastructures.hashmap.hashing;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
// implementation of generic hashmaps using array of Linked Lists
|
||||||
|
|
||||||
|
public class GenericHashMapUsingArray<K, V> {
|
||||||
|
private int size; // n (total number of key-value pairs)
|
||||||
|
private LinkedList<Node>[] buckets; // N = buckets.length
|
||||||
|
private float lf = 0.75f;
|
||||||
|
|
||||||
|
public GenericHashMapUsingArray() {
|
||||||
|
initBuckets(16);
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
// load factor = 0.75 means if we need to add 100 items and we have added
|
||||||
|
// 75, then adding 76th item it will double the size, copy all elements
|
||||||
|
// & then add 76th item.
|
||||||
|
|
||||||
|
private void initBuckets(int N) {
|
||||||
|
buckets = new LinkedList[N];
|
||||||
|
for (int i = 0; i < buckets.length; i++) {
|
||||||
|
buckets[i] = new LinkedList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(K key, V value) {
|
||||||
|
int bucketIndex = hashFunction(key);
|
||||||
|
LinkedList<Node> nodes = buckets[bucketIndex];
|
||||||
|
for (Node node : nodes) { // if key present => update
|
||||||
|
if (node.key.equals(key)) {
|
||||||
|
node.value = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// key is not present => insert
|
||||||
|
nodes.add(new Node(key, value));
|
||||||
|
size++;
|
||||||
|
|
||||||
|
if ((float) size / buckets.length > lf) {
|
||||||
|
reHash();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// tells which bucket to go to
|
||||||
|
private int hashFunction(K key) {
|
||||||
|
int hc = key.hashCode();
|
||||||
|
return Math.abs(hc) % buckets.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reHash() {
|
||||||
|
System.out.println("Rehashing!");
|
||||||
|
LinkedList<Node>[] old = buckets;
|
||||||
|
initBuckets(old.length * 2);
|
||||||
|
this.size = 0;
|
||||||
|
|
||||||
|
for (LinkedList<Node> nodes : old) {
|
||||||
|
for (Node node : nodes) {
|
||||||
|
put(node.key, node.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(K key) {
|
||||||
|
int bucketIndex = hashFunction(key);
|
||||||
|
LinkedList<Node> nodes = buckets[bucketIndex];
|
||||||
|
|
||||||
|
Node target = null;
|
||||||
|
for (Node node : nodes) {
|
||||||
|
if (node.key.equals(key)) {
|
||||||
|
target = node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodes.remove(target);
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return this.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public V get(K key) {
|
||||||
|
int bucketIndex = hashFunction(key);
|
||||||
|
LinkedList<Node> nodes = buckets[bucketIndex];
|
||||||
|
for (Node node : nodes) {
|
||||||
|
if (node.key.equals(key)) {
|
||||||
|
return node.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
builder.append("{");
|
||||||
|
for (LinkedList<Node> nodes : buckets) {
|
||||||
|
for (Node node : nodes) {
|
||||||
|
builder.append(node.key);
|
||||||
|
builder.append(" : ");
|
||||||
|
builder.append(node.value);
|
||||||
|
builder.append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.append("}");
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsKey(K key) {
|
||||||
|
return get(key) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Node {
|
||||||
|
K key;
|
||||||
|
V value;
|
||||||
|
|
||||||
|
public Node(K key, V value) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
package com.thealgorithms.datastructures.hashmap.hashing;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
public class GenericHashMapUsingArrayList<K, V> {
|
||||||
|
ArrayList<LinkedList<Node>> buckets;
|
||||||
|
private float lf = 0.5f;
|
||||||
|
private int size;
|
||||||
|
|
||||||
|
public GenericHashMapUsingArrayList() {
|
||||||
|
buckets = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
buckets.add(new LinkedList<>());
|
||||||
|
}
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(K key, V value) {
|
||||||
|
int hash = Math.abs(key.hashCode() % buckets.size());
|
||||||
|
LinkedList<Node> nodes = buckets.get(hash);
|
||||||
|
|
||||||
|
for (Node node : nodes) {
|
||||||
|
if (node.key.equals(key)) {
|
||||||
|
node.val = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes.add(new Node(key, value));
|
||||||
|
size++;
|
||||||
|
|
||||||
|
if ((float) size / buckets.size() > lf) {
|
||||||
|
reHash();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reHash() {
|
||||||
|
ArrayList<LinkedList<Node>> old = buckets;
|
||||||
|
buckets = new ArrayList<>();
|
||||||
|
size = 0;
|
||||||
|
for (int i = 0; i < old.size() * 2; i++) {
|
||||||
|
buckets.add(new LinkedList<>());
|
||||||
|
}
|
||||||
|
for (LinkedList<Node> nodes : buckets) {
|
||||||
|
for (Node node : nodes) {
|
||||||
|
put(node.key, node.val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public V get(K key) {
|
||||||
|
int hash = Math.abs(key.hashCode() % buckets.size());
|
||||||
|
LinkedList<Node> nodes = buckets.get(hash);
|
||||||
|
for (Node node : nodes) {
|
||||||
|
if (node.key.equals(key)) {
|
||||||
|
return node.val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(K key) {
|
||||||
|
int hash = Math.abs(key.hashCode() % buckets.size());
|
||||||
|
LinkedList<Node> nodes = buckets.get(hash);
|
||||||
|
|
||||||
|
Node target = null;
|
||||||
|
for (Node node : nodes) {
|
||||||
|
if (node.key.equals(key)) {
|
||||||
|
target = node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodes.remove(target);
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsKey(K key) {
|
||||||
|
return get(key) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return this.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append("{");
|
||||||
|
for (LinkedList<Node> nodes : buckets) {
|
||||||
|
for (Node node : nodes) {
|
||||||
|
builder.append(node.key);
|
||||||
|
builder.append(" : ");
|
||||||
|
builder.append(node.val);
|
||||||
|
builder.append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.append("}");
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Node {
|
||||||
|
K key;
|
||||||
|
V val;
|
||||||
|
|
||||||
|
public Node(K key, V val) {
|
||||||
|
this.key = key;
|
||||||
|
this.val = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package com.thealgorithms.datastructures.hashmap.hashing;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class GenericHashMapUsingArrayListTest {
|
||||||
|
@Test
|
||||||
|
void testGenericHashmapWhichUsesArrayAndBothKeyAndValueAreStrings() {
|
||||||
|
GenericHashMapUsingArrayList<String, String> map = new GenericHashMapUsingArrayList<>();
|
||||||
|
map.put("USA", "Washington DC");
|
||||||
|
map.put("Nepal", "Kathmandu");
|
||||||
|
map.put("India", "New Delhi");
|
||||||
|
map.put("Australia", "Sydney");
|
||||||
|
assertNotNull(map);
|
||||||
|
assertEquals(4, map.size());
|
||||||
|
assertEquals("Kathmandu", map.get("Nepal"));
|
||||||
|
assertEquals("Sydney", map.get("Australia"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGenericHashmapWhichUsesArrayAndKeyIsStringValueIsInteger() {
|
||||||
|
GenericHashMapUsingArrayList<String, Integer> map = new GenericHashMapUsingArrayList<>();
|
||||||
|
map.put("USA", 87);
|
||||||
|
map.put("Nepal", 25);
|
||||||
|
map.put("India", 101);
|
||||||
|
map.put("Australia", 99);
|
||||||
|
assertNotNull(map);
|
||||||
|
assertEquals(4, map.size());
|
||||||
|
assertEquals(25, map.get("Nepal"));
|
||||||
|
assertEquals(99, map.get("Australia"));
|
||||||
|
map.remove("Nepal");
|
||||||
|
assertFalse(map.containsKey("Nepal"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGenericHashmapWhichUsesArrayAndKeyIsIntegerValueIsString() {
|
||||||
|
GenericHashMapUsingArrayList<Integer, String> map = new GenericHashMapUsingArrayList<>();
|
||||||
|
map.put(101, "Washington DC");
|
||||||
|
map.put(34, "Kathmandu");
|
||||||
|
map.put(46, "New Delhi");
|
||||||
|
map.put(89, "Sydney");
|
||||||
|
assertNotNull(map);
|
||||||
|
assertEquals(4, map.size());
|
||||||
|
assertEquals("Sydney", map.get(89));
|
||||||
|
assertEquals("Washington DC", map.get(101));
|
||||||
|
assertTrue(map.containsKey(46));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package com.thealgorithms.datastructures.hashmap.hashing;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class GenericHashMapUsingArrayTest {
|
||||||
|
@Test
|
||||||
|
void testGenericHashmapWhichUsesArrayAndBothKeyAndValueAreStrings() {
|
||||||
|
GenericHashMapUsingArray<String, String> map = new GenericHashMapUsingArray<>();
|
||||||
|
map.put("USA", "Washington DC");
|
||||||
|
map.put("Nepal", "Kathmandu");
|
||||||
|
map.put("India", "New Delhi");
|
||||||
|
map.put("Australia", "Sydney");
|
||||||
|
assertNotNull(map);
|
||||||
|
assertEquals(4, map.size());
|
||||||
|
assertEquals("Kathmandu", map.get("Nepal"));
|
||||||
|
assertEquals("Sydney", map.get("Australia"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGenericHashmapWhichUsesArrayAndKeyIsStringValueIsInteger() {
|
||||||
|
GenericHashMapUsingArray<String, Integer> map = new GenericHashMapUsingArray<>();
|
||||||
|
map.put("USA", 87);
|
||||||
|
map.put("Nepal", 25);
|
||||||
|
map.put("India", 101);
|
||||||
|
map.put("Australia", 99);
|
||||||
|
assertNotNull(map);
|
||||||
|
assertEquals(4, map.size());
|
||||||
|
assertEquals(25, map.get("Nepal"));
|
||||||
|
assertEquals(99, map.get("Australia"));
|
||||||
|
map.remove("Nepal");
|
||||||
|
assertFalse(map.containsKey("Nepal"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGenericHashmapWhichUsesArrayAndKeyIsIntegerValueIsString() {
|
||||||
|
GenericHashMapUsingArray<Integer, String> map = new GenericHashMapUsingArray<>();
|
||||||
|
map.put(101, "Washington DC");
|
||||||
|
map.put(34, "Kathmandu");
|
||||||
|
map.put(46, "New Delhi");
|
||||||
|
map.put(89, "Sydney");
|
||||||
|
assertNotNull(map);
|
||||||
|
assertEquals(4, map.size());
|
||||||
|
assertEquals("Sydney", map.get(89));
|
||||||
|
assertEquals("Washington DC", map.get(101));
|
||||||
|
assertTrue(map.containsKey(46));
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user