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+ }