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 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+ private 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 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 (Entry <K ,V >entry :table ) {
68+ if (entry !=null &&entry .getValue () ==value ) {
69+ return true ;
70+ }
71+ }
72+
73+ return false ;
74+ }
75+
76+ @ Override /** Return a set of entries in the map */
77+ public java .util .Set <Entry <K ,V >>entrySet () {
78+ java .util .Set <Entry <K ,V >>set =new java .util .HashSet <>();
79+
80+ for (Entry <K ,V >entry :table ) {
81+ if (entry !=null )
82+ set .add (entry );
83+ }
84+
85+ return set ;
86+ }
87+
88+ @ Override /** Return the value that matched the specified key */
89+ public V get (K key ) {
90+ int index =hash (key .hashCode ());
91+ int i =index -1 ;
92+
93+ while (i !=index && (table .get (index ) ==null ||
94+ table .get (index ).getKey () !=key )) {
95+ index ++;
96+ index %=capacity ;
97+ }
98+
99+ if (table .get (index ).getKey () ==key ) {
100+ return table .get (index ).getValue ();
101+ }
102+
103+ return null ;
104+ }
105+
106+ @ Override /** Return a set of values that match the key in the map */
107+ public java .util .Set <V >getAll (K key ) {
108+ java .util .Set <V >set =new java .util .HashSet <>();
109+ int index =hash (key .hashCode ());
110+ int i =index -1 ;
111+
112+ while (i !=index ) {
113+ if (table .get (index ) !=null &&table .get (index ).getKey () ==key ) {
114+ set .add (table .get (index ).getValue ());
115+ }
116+ index ++;
117+ index %=capacity ;
118+ }
119+
120+ return set ;
121+ }
122+
123+ @ Override /** Return true if this map contains no entries */
124+ public boolean isEmpty () {
125+ return size ==0 ;
126+ }
127+
128+ @ Override /** Return a set consisting of the keys in this map */
129+ public java .util .Set <K >keySet () {
130+ java .util .Set <K >set =new java .util .HashSet <>();
131+
132+ for (Entry <K ,V >entry :table ) {
133+ if (entry !=null )
134+ set .add (entry .getKey ());
135+ }
136+
137+ return set ;
138+ }
139+
140+ @ Override /** Add an entry (key, value) into the map */
141+ public V put (K key ,V value ) {
142+ int index =hash (key .hashCode ());
143+
144+ while (table .get (index ) !=null ) {
145+ index ++;
146+ index %=capacity ;
147+ }
148+
149+ if (size >=capacity *loadFactorThreshold ) {
150+ if (capacity ==MAXIMUM_CAPACITY ) {
151+ throw new RuntimeException ("Exceeding maximum capacity" );
152+ }
153+ rehash ();
154+ }
155+
156+ // Add a new entry (key, value) to hash table
157+ table .set (index ,new MyMap .Entry <K ,V >(key ,value ));
158+
159+ size ++;// Increase size
160+
161+ return value ;
162+ }
163+
164+ @ Override /** Remove the entry for the specified key */
165+ public void remove (K key ) {
166+ int index =hash (key .hashCode ());
167+ int i =index -1 ;
168+
169+ while (i !=index && (table .get (index ) ==null ||
170+ table .get (index ).getKey () !=key )) {
171+ index ++;
172+ index %=capacity ;
173+ }
174+
175+ if (table .get (index ).getKey () ==key ) {
176+ table .remove (index );
177+ }
178+ }
179+
180+ @ Override /** Return the number of entries in this map */
181+ public int size () {
182+ return size ;
183+ }
184+
185+ @ Override /** Return a set consisting of all the values in this map */
186+ public java .util .Set <V >values () {
187+ java .util .Set <V >set =new java .util .HashSet <>();
188+
189+ for (Entry <K ,V >entry :table ) {
190+ if (entry !=null ) {
191+ set .add (entry .getValue ());
192+ }
193+ }
194+
195+ return set ;
196+ }
197+
198+ /** Hash function */
199+ private int hash (int hashCode ) {
200+ return supplementalHash (hashCode ) & (capacity -1 );
201+ }
202+
203+ /** Ensure the hashing is evenly distributed */
204+ private int supplementalHash (int h ) {
205+ h ^= (h >>>20 ) ^ (h >>>12 );
206+ return h ^ (h >>>7 ) ^ (h >>>4 );
207+ }
208+
209+ /** Return a power of 2 for initialCapacity */
210+ private int trimToPowerOf2 (int initialcapacity ) {
211+ int capacity =1 ;
212+ while (capacity <initialcapacity ) {
213+ capacity <<=1 ;
214+ }
215+
216+ return capacity ;
217+
218+ }
219+
220+ /** Remove all entries from map */
221+ private void removeEntries () {
222+ table .clear ();
223+ }
224+
225+ /** Rehash the map */
226+ private void rehash () {
227+ capacity <<=1 ;// Same as *= 2. <= is more efficient
228+ for (int i =size +1 ;i <capacity ;i ++) {
229+ table .add (null );
230+ }
231+ }
232+
233+ @ Override
234+ public String toString () {
235+ StringBuilder builder =new StringBuilder ("[" );
236+
237+ for (Entry <K ,V >entry :table ) {
238+ if (entry !=null &&size >0 ) {
239+ builder .append (entry );
240+ }
241+ }
242+
243+ builder .append ("]" );
244+ return builder .toString ();
245+ }
246+ }