Skip to content
Open
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 74 additions & 1 deletion src/main/java/core/basesyntax/MyHashMap.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,92 @@
package core.basesyntax;

import java.util.Objects;

public class MyHashMap<K, V> implements MyMap<K, V> {
private static final int DEFAULT_INITIAL_CAPACITY = 16;
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
private static final int HASH_MASK = Integer.MAX_VALUE;

public MyHashMap() {
table = new Node[DEFAULT_INITIAL_CAPACITY];
threshold = (int) (DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
}

@Override
public void put(K key, V value) {
if (size >= threshold) {
resize();
}
int hash = hash(key);
int index = (hash & HASH_MASK) % table.length;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Index calculation is duplicated, this appears in more than one place:

int index = (hash & HASH_MASK) % table.length;

It would be cleaner to extract it into a private helper method, for example:

private int getIndex(int hash, int length)

Node<K, V> current = table[index];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This violates checklist item #2: 'Any magic numbers should be constants'. While using Integer.MAX_VALUE is better than a raw hex value, the requirement is to create your own private static final constant with a descriptive name (e.g., POSITIVE_INTEGER_MASK) to make the intent of the bitwise operation clear.

while (current != null) {
if (current.hash == hash && Objects.equals(current.key, key)) {
current.value = value;
return;
}
current = current.next;
}

Node<K, V> newNode = new Node<>(hash, key, value, table[index]);
table[index] = newNode;
size++;
}

@Override
public V getValue(K key) {
int hash = hash(key);
int index = (hash & HASH_MASK) % table.length;
Node<K, V> current = table[index];
while (current != null) {
if (current.hash == hash && Objects.equals(current.key, key)) {
return current.value;
}
current = current.next;
}
return null;
}

@Override
public int getSize() {
return 0;
return size;
}

private void resize() {
int newCapacity = table.length * 2;
Node<K, V>[] newTable = new Node[newCapacity];
for (Node<K, V> node : table) {
while (node != null) {
Node<K, V> next = node.next;
int index = (node.hash & HASH_MASK) % newCapacity;
node.next = newTable[index];
newTable[index] = node;
node = next;
}
}
table = newTable;
threshold = (int) (newCapacity * DEFAULT_LOAD_FACTOR);
}

private int hash(K key) {
return key == null ? 0 : key.hashCode();
}

private class Node<K, V> {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Node should be static:

Suggested change
private class Node<K, V> {
private static class Node<K, V> {

Since Node does not need access to the outer MyHashMap instance, making it static avoids storing an unnecessary reference to the outer object.

private final int hash;
private final K key;
private V value;
private Node<K, V> next;

public Node(int hash, K key, V value, Node<K, V> next) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since Node is used only inside MyHashMap, the constructor should also be restricted:

Suggested change
public Node(int hash, K key, V value, Node<K, V> next) {
private Node(int hash, K key, V value, Node<K, V> next) {

this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
}

private Node<K, V>[] table;
private int size;
private int threshold;
}
Loading