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+ @ Override /** Remove all of the entries from this map */
51+ public void clear () {
52+ size =0 ;
53+ removeEntries ();
54+ }
55+
56+ @ Override /** Return true if the specified key is in the map */
57+ public boolean containsKey (K key ) {
58+ if (get (key ) !=null )
59+ return true ;
60+ else
61+ return false ;
62+ }
63+
64+ @ Override /** Return true if this map contains the value */
65+ public boolean containsValue (V value ) {
66+ for (int i =0 ;i <capacity ;i ++) {
67+ if (table .get (i ) !=null &&table .get (i ).getValue () ==value )
68+ return true ;
69+ }
70+
71+ return false ;
72+ }
73+
74+ @ Override /** Return a set of entries in the map */
75+ public java .util .Set <MyMap .Entry <K ,V >>entrySet () {
76+ java .util .Set <MyMap .Entry <K ,V >>set =
77+ new java .util .HashSet <>();
78+
79+ for (int i =0 ;i <capacity ;i ++) {
80+ if (table .get (i ) !=null ) {
81+ set .add (table .get (i ));
82+ }
83+ }
84+
85+ return set ;
86+ }
87+
88+ @ Override /** Return the value that matches the specified key */
89+ public V get (K key ) {
90+ int index =hash (key .hashCode ());
91+ int i =index -1 ;// One cycle of the arraylist
92+
93+ // While index is empty or a collision occurs check the next index
94+ while (index !=i && (table .get (index ) ==null ||
95+ table .get (index ).getKey () !=key )) {
96+ index ++;
97+ index %=capacity ;
98+ }
99+
100+ if (table .get (index ).getKey () ==key ) {
101+ return table .get (index ).getValue ();
102+ }
103+
104+ return null ;
105+ }
106+
107+ @ Override /** Return true if this map contain 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 <K >();
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+ return set ;
122+ }
123+
124+ @ Override /** Add an entry (key, value) into the map */
125+ public V put (K key ,V value ) {
126+ int index =hash (key .hashCode ());
127+
128+ while (table .get (index ) !=null ) {
129+ // Add a new entry (key, value)
130+ if (table .get (index ).getKey () ==key ) {
131+ Entry <K ,V >entry =table .get (index );
132+ V oldvalue =entry .getValue ();
133+ // Replace old value with new value
134+ entry .value =value ;
135+ table .set (index ,entry );
136+ // Return the old value for the key
137+ return oldvalue ;
138+ }
139+
140+ // Collision check if the next index is available
141+ index ++;
142+ index %=capacity ;
143+ }
144+
145+ // Check load factor
146+ if (size >=capacity *loadFactorThreshold ) {
147+ if (capacity ==MAXIMUM_CAPACITY )
148+ throw new RuntimeException ("Exceeding maximum capacity" );
149+ rehash ();
150+ }
151+
152+ // Add a new entry (key, value) to hashtable
153+ table .set (index ,new MyMap .Entry <K ,V >(key ,value ));
154+
155+ size ++;// Increase size
156+
157+ return value ;
158+ }
159+
160+ @ Override /** Remove the entry for the specified key */
161+ public void remove (K key ) {
162+ int index =hash (key .hashCode ());
163+ int i =index -1 ;// One cycle of the arraylist
164+
165+ // While index is empty or there is a
166+ // collision check the next index in cycle
167+ while ((table .get (index ) ==null ||
168+ table .get (index ).getKey () !=key ) &&i !=index ) {
169+ index ++;
170+ index %=capacity ;
171+ }
172+
173+ // Remove the entry that matches the key
174+ if (table .get (index ).getKey () ==key ) {
175+ table .remove (index );
176+ }
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 values in this map */
186+ public java .util .Set <V >values () {
187+ java .util .Set <V >set =new java .util .HashSet <>();
188+
189+ for (int i =0 ;i <capacity ;i ++) {
190+ if (table .get (i ) !=null )
191+ set .add (table .get (i ).getValue ());
192+ }
193+
194+ return set ;
195+ }
196+
197+ /** Hash function */
198+ private int hash (int hashCode ) {
199+ return supplementalHash (hashCode ) & (capacity -1 );
200+ }
201+
202+ /** Ensure the hashing is evenly distributed */
203+ private static int supplementalHash (int h ) {
204+ h ^= (h >>>20 ) ^ (h >>>12 );
205+ return h ^ (h >>>7 ) ^ (h >>>4 );
206+ }
207+
208+ /** Return a power of 2 for initialCapacity */
209+ private int trimToPowerOf2 (int initialCapacity ) {
210+ int capacity =1 ;
211+ while (capacity <initialCapacity ) {
212+ capacity <<=1 ;
213+ }
214+
215+ return capacity ;
216+ }
217+
218+ /** Remove all entries from map */
219+ private void removeEntries () {
220+ table .clear ();
221+ }
222+
223+ /** Rehash the map */
224+ private void rehash () {
225+ capacity <<=1 ;// Same as capacity *= 2. <= is more efficient
226+ for (int i = (size +1 );i <capacity ;i ++) {
227+ table .add (null );
228+ }
229+ }
230+
231+ @ Override /** Return a string repesentation for this map */
232+ public String toString () {
233+ StringBuilder builder =new StringBuilder ("[" );
234+
235+ for (Entry <K ,V >entry :table ) {
236+ if (entry !=null &&table .size () >0 )
237+ builder .append (entry );
238+ }
239+
240+ builder .append ("]" );
241+ return builder .toString ();
242+ }
243+ }