1
+ import java .util .ArrayList ;
2
+
3
+ public class MyHashMap <K ,V >implements MyMap <K ,V > {
4
+ // Define the default hash-table size. Must be a power of 2
5
+ private static int DEFAULT_INITIAL_CAPACITY =4 ;
6
+
7
+ // Define the maximum hash-table size. 1 << 30 is same as 2^30
8
+ private static int MAXIMUM_CAPACITY =1 <<30 ;
9
+
10
+ // Current hash-table capacity. Capacity is a power of 2
11
+ private int capacity ;
12
+
13
+ // Define default load factor
14
+ private static float DEFAULT_MAX_LOAD_FACTOR =0.5f ;
15
+
16
+ // Specify a load factor used in the hash table
17
+ private float loadFactorThreshold ;
18
+
19
+ // The number of entries in the map
20
+ private int size =0 ;
21
+
22
+ // Hash table is an ArrayList
23
+ ArrayList <MyMap .Entry <K ,V >>table ;
24
+
25
+ /** Construct a map with the default capacity and load factor */
26
+ public MyHashMap () {
27
+ this (DEFAULT_INITIAL_CAPACITY ,DEFAULT_MAX_LOAD_FACTOR );
28
+ }
29
+
30
+ /** Construct a map with the specified initial capacity and
31
+ * default load factor */
32
+ public MyHashMap (int initialCapacity ) {
33
+ this (initialCapacity ,DEFAULT_MAX_LOAD_FACTOR );
34
+ }
35
+
36
+ /** Construct a map with the specified initial capacity
37
+ * and load factor */
38
+ public MyHashMap (int initialCapacity ,float loadFactorThreshold ) {
39
+ if (initialCapacity >MAXIMUM_CAPACITY )
40
+ this .capacity =MAXIMUM_CAPACITY ;
41
+ else
42
+ this .capacity =trimToPowerOf2 (initialCapacity );
43
+
44
+ this .loadFactorThreshold =loadFactorThreshold ;
45
+ table =new ArrayList <>();
46
+ for (int i =0 ;i <capacity ;i ++) {
47
+ table .add (null );
48
+ }
49
+ }
50
+
51
+ @ Override /** Remove all of the entries from this map */
52
+ public void clear () {
53
+ size =0 ;
54
+ removeEntries ();
55
+ }
56
+
57
+ @ Override /** Return true if the specified key is in the map */
58
+ public boolean containsKey (K key ) {
59
+ if (get (key ) !=null )
60
+ return true ;
61
+ else
62
+ return false ;
63
+ }
64
+
65
+ @ Override /** Return true if this map contains the value */
66
+ public boolean containsValue (V value ) {
67
+ for (int i =0 ;i <capacity ;i ++) {
68
+ if (table .get (i ) !=null &&table .get (i ).getValue () ==value )
69
+ return true ;
70
+ }
71
+
72
+ return false ;
73
+ }
74
+
75
+ @ Override /** Return a set of entries in the map */
76
+ public java .util .Set <MyMap .Entry <K ,V >>entrySet () {
77
+ java .util .Set <MyMap .Entry <K ,V >>set =
78
+ new java .util .HashSet <>();
79
+
80
+ for (int i =0 ;i <capacity ;i ++) {
81
+ if (table .get (i ) !=null ) {
82
+ set .add (table .get (i ));
83
+ }
84
+ }
85
+
86
+ return set ;
87
+ }
88
+
89
+ @ Override /** Return the value that matches the specified key */
90
+ public V get (K key ) {
91
+ int index =hash (key .hashCode ());
92
+ int i =index -1 ;// One cycle of the arraylist
93
+ int j =0 ;
94
+
95
+ while (index !=i && (table .get (index ) ==null ||
96
+ table .get (index ).getKey () !=key )) {
97
+ index +=Math .pow (j ++,2 );
98
+ index %=capacity ;
99
+ }
100
+
101
+ if (table .get (index ).getKey () ==key )
102
+ return table .get (index ).getValue ();
103
+
104
+ return null ;
105
+ }
106
+
107
+ @ Override /** Return true if this map contains no entries */
108
+ public boolean isEmpty () {
109
+ return size ==0 ;
110
+ }
111
+
112
+ @ Override /** Return a set consisting of the keys in this map */
113
+ public java .util .Set <K >keySet () {
114
+ java .util .Set <K >set =new java .util .HashSet <>();
115
+
116
+ for (int i =0 ;i <capacity ;i ++) {
117
+ if (table .get (i ) !=null ) {
118
+ set .add (table .get (i ).getKey ());
119
+ }
120
+ }
121
+
122
+ return set ;
123
+ }
124
+
125
+ @ Override /** Add an entry (key, value) into the map */
126
+ public V put (K key ,V value ) {
127
+ int index =hash (key .hashCode ());
128
+ int j =0 ;
129
+
130
+ while (table .get (index ) !=null ) {
131
+ // Add a new entry (key, value)
132
+ if (table .get (index ).getKey () ==key ) {
133
+ Entry <K ,V >entry =table .get (index );
134
+ V oldValue =entry .getValue ();
135
+ // Replace old value with new value
136
+ entry .value =value ;
137
+ table .set (index ,entry );
138
+ // Return the old value for the key
139
+ return oldValue ;
140
+ }
141
+
142
+ index +=Math .pow (j ++,2 );
143
+ index %=capacity ;
144
+ }
145
+
146
+ // Check load factor
147
+ if (size >=capacity *loadFactorThreshold ) {
148
+ if (capacity ==MAXIMUM_CAPACITY )
149
+ throw new RuntimeException ("Exceeding maximum capacity" );
150
+ rehash ();
151
+ }
152
+
153
+ // Add a new entry(key, value) to hashtable
154
+ table .set (index ,new MyMap .Entry <K ,V >(key ,value ));
155
+
156
+ size ++;// Increase size
157
+
158
+ return value ;
159
+ }
160
+
161
+ @ Override /** Remove the entry for the specified key */
162
+ public void remove (K key ) {
163
+ int index =hash (key .hashCode ());
164
+ int i =index -1 ;// One cycle of the arraylist
165
+ int j =0 ;
166
+
167
+ while ((table .get (index ) ==null ||
168
+ table .get (index ).getKey () !=key ) &&i !=index ) {
169
+ index +=Math .pow (j ++,2 );
170
+ index %=capacity ;
171
+ }
172
+
173
+ if (table .get (index ).getKey () ==key )
174
+ table .remove (index );
175
+ }
176
+
177
+ @ Override /** Return the number of entries in this map */
178
+ public int size () {
179
+ return size ;
180
+ }
181
+
182
+ @ Override /** Return a set consisting of values in this map */
183
+ public java .util .Set <V >values () {
184
+ java .util .Set <V >set =new java .util .HashSet <>();
185
+
186
+ for (int i =0 ;i <capacity ;i ++) {
187
+ if (table .get (i ) !=null )
188
+ set .add (table .get (i ).getValue ());
189
+ }
190
+
191
+ return set ;
192
+ }
193
+ /** Hash function */
194
+ private int hash (int hashCode ) {
195
+ return supplementalHash (hashCode ) & (capacity -1 );
196
+ }
197
+
198
+ /** Ensure the hashing is evenly distributed */
199
+ private static int supplementalHash (int h ) {
200
+ h ^= (h >>>20 ) ^ (h >>>12 );
201
+ return h ^ (h >>>7 ) ^ (h >>>4 );
202
+ }
203
+
204
+ /** Return a power of 2 for initialCapacity */
205
+ private int trimToPowerOf2 (int initialCapacity ) {
206
+ int capacity =1 ;
207
+ while (capacity <initialCapacity ) {
208
+ capacity <<=1 ;
209
+ }
210
+
211
+ return capacity ;
212
+ }
213
+
214
+ /** Remove all entries from map */
215
+ private void removeEntries () {
216
+ table .clear ();
217
+ }
218
+
219
+ /** Rehash the map */
220
+ private void rehash () {
221
+ capacity <<=1 ;// Same as capacity *= 2. <= is more efficient
222
+ for (int i = (size +1 );i <capacity ;i ++) {
223
+ table .add (null );
224
+ }
225
+ }
226
+
227
+ @ Override /** Return a string repersentation for this map */
228
+ public String toString () {
229
+ StringBuilder builder =new StringBuilder ("[" );
230
+
231
+ for (Entry <K ,V >entry :table ) {
232
+ if (entry !=null &&table .size () >0 )
233
+ builder .append (entry );
234
+ }
235
+
236
+ builder .append ("]" );
237
+ return builder .toString ();
238
+ }
239
+ }