forked from TheAlgorithms/Java
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathImmutableHashMap.java
More file actions
115 lines (100 loc) · 2.93 KB
/
ImmutableHashMap.java
File metadata and controls
115 lines (100 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package com.thealgorithms.datastructures.hashmap.hashing;
/**
* Immutable HashMap implementation using separate chaining.
*
* <p>This HashMap does not allow modification of existing instances.
* Any update operation returns a new ImmutableHashMap.
*
* @param <K> key type
* @param <V> value type
*/
public final class ImmutableHashMap<K, V> {
private static final int DEFAULT_CAPACITY = 16;
private final Node<K, V>[] table;
private final int size;
/**
* Private constructor to enforce immutability.
*/
private ImmutableHashMap(Node<K, V>[] table, int size) {
this.table = table;
this.size = size;
}
/**
* Creates an empty ImmutableHashMap.
*
* @param <K> key type
* @param <V> value type
* @return empty ImmutableHashMap
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static <K, V> ImmutableHashMap<K, V> empty() {
Node<K, V>[] table = (Node<K, V>[]) new Node[DEFAULT_CAPACITY];
return new ImmutableHashMap<>(table, 0);
}
/**
* Returns a new ImmutableHashMap with the given key-value pair added.
*
* @param key key to add
* @param value value to associate
* @return new ImmutableHashMap instance
*/
public ImmutableHashMap<K, V> put(K key, V value) {
Node<K, V>[] newTable = table.clone();
int index = hash(key);
newTable[index] = new Node<>(key, value, newTable[index]);
return new ImmutableHashMap<>(newTable, size + 1);
}
/**
* Retrieves the value associated with the given key.
*
* @param key key to search
* @return value if found, otherwise null
*/
public V get(K key) {
int index = hash(key);
Node<K, V> current = table[index];
while (current != null) {
if ((key == null && current.key == null) || (key != null && key.equals(current.key))) {
return current.value;
}
current = current.next;
}
return null;
}
/**
* Checks whether the given key exists in the map.
*
* @param key key to check
* @return true if key exists, false otherwise
*/
public boolean containsKey(K key) {
return get(key) != null;
}
/**
* Returns the number of key-value pairs.
*
* @return size of the map
*/
public int size() {
return size;
}
/**
* Computes hash index for a given key.
*/
private int hash(K key) {
return key == null ? 0 : (key.hashCode() & Integer.MAX_VALUE) % table.length;
}
/**
* Node class for separate chaining.
*/
private static final class Node<K, V> {
private final K key;
private final V value;
private final Node<K, V> next;
private Node(K key, V value, Node<K, V> next) {
this.key = key;
this.value = value;
this.next = next;
}
}
}