@@ -5,10 +5,11 @@ class HashMap {
55
66 /**
77 * Initialize array that holds the values. Default is size 1,000
8- * @param {number } size
8+ * @param {number } initialCapacity
99 */
10- constructor ( size = 4 ) {
11- this . array = new Array ( size ) ;
10+ constructor ( initialCapacity = 2 ) {
11+ this . buckets = new Array ( initialCapacity ) ;
12+ this . collisions = 0 ;
1213 }
1314
1415 /**
@@ -17,11 +18,12 @@ class HashMap {
1718 * @param {any } value
1819 */
1920 set ( key , value ) {
20- const index = this . getIndex ( key ) ;
21- if ( this . array [ index ] ) {
22- this . array [ index ] . push ( { key, value} ) ;
21+ const bucketIndex = this . getIndex ( key ) ;
22+ if ( this . buckets [ bucketIndex ] ) {
23+ this . buckets [ bucketIndex ] . push ( { key, value} ) ;
24+ if ( this . buckets [ bucketIndex ] . length > 1 ) { this . collisions ++ ; }
2325 } else {
24- this . array [ index ] = [ { key, value} ] ;
26+ this . buckets [ bucketIndex ] = [ { key, value} ] ;
2527 }
2628 return this ;
2729 }
@@ -31,9 +33,9 @@ class HashMap {
3133 * @param {any } key
3234 */
3335 get ( key ) {
34- const hashIndex = this . getIndex ( key ) ;
35- for ( let index = 0 ; index < this . array [ hashIndex ] . length ; index ++ ) {
36- const entry = this . array [ hashIndex ] [ index ] ;
36+ const bucketIndex = this . getIndex ( key ) ;
37+ for ( let arrayIndex = 0 ; arrayIndex < this . buckets [ bucketIndex ] . length ; arrayIndex ++ ) {
38+ const entry = this . buckets [ bucketIndex ] [ arrayIndex ] ;
3739 if ( entry . key === key ) {
3840 return entry . value
3941 }
@@ -47,11 +49,11 @@ class HashMap {
4749 */
4850 hash ( key ) {
4951 let hashValue = 0 ;
50- const stringKey = key . toString ( ) ;
52+ const stringTypeKey = ` ${ key } ${ typeof key } ` ;
5153
52- for ( let index = 0 ; index < stringKey . length ; index ++ ) {
53- const charCode = stringKey . charCodeAt ( index ) ;
54- hashValue += charCode ;
54+ for ( let index = 0 ; index < stringTypeKey . length ; index ++ ) {
55+ const charCode = stringTypeKey . charCodeAt ( index ) ;
56+ hashValue += charCode << ( index * 8 ) ;
5557 }
5658
5759 return hashValue ;
@@ -63,21 +65,64 @@ class HashMap {
6365 */
6466 getIndex ( key ) {
6567 const indexHash = this . hash ( key ) ;
66- const index = indexHash % this . array . length ;
68+ const index = indexHash % this . buckets . length ;
6769 return index ;
6870 }
6971}
7072
73+ // Usage:
7174const assert = require ( 'assert' ) ;
7275const hashMap = new HashMap ( ) ;
7376
7477hashMap . set ( 'cat' , 2 ) ;
7578hashMap . set ( 'rat' , 7 ) ;
7679hashMap . set ( 'dog' , 1 ) ;
77- hashMap . set ( 'art' , 0 ) ; // <-- collision with rat
80+ hashMap . set ( 'art' , 8 ) ;
7881
79- console . log ( hashMap . array ) ;
82+ console . log ( 'collisions: ' , hashMap . collisions ) ;
83+ console . log ( 'hashMap.buckets\n' , hashMap . buckets ) ;
84+ /*
85+ bucket #0: [ { key: 'cat', value: 2 }, { key: 'dog', value: 1 } ]
86+ bucket #1: [ { key: 'rat', value: 7 }, { key: 'dog', value: 1 } ]
87+ */
8088
81- assert . equal ( hashMap . get ( 'cat' ) , 2 ) ;
82- assert . equal ( hashMap . get ( 'rat' ) , 7 ) ;
83- assert . equal ( hashMap . get ( 'dog' ) , 1 ) ;
89+ assert . equal ( hashMap . get ( 'art' ) , 8 ) ; // this one is ok
90+ assert . equal ( hashMap . get ( 'cat' ) , 2 ) ; // Good. Didn't got overwritten by art
91+ assert . equal ( hashMap . get ( 'rat' ) , 7 ) ; // Good. Didn't got overwritten by art
92+ assert . equal ( hashMap . get ( 'dog' ) , 1 ) ; // Good. Didn't got overwritten by art
93+
94+
95+ //
96+
97+
98+ const hashMapSize10 = new HashMap ( 10 ) ;
99+
100+ hashMapSize10 . set ( 'cat' , 2 ) ;
101+ hashMapSize10 . set ( 'rat' , 7 ) ;
102+ hashMapSize10 . set ( 'dog' , 1 ) ;
103+ hashMapSize10 . set ( 'art' , 8 ) ;
104+
105+ console . log ( 'collisions: ' , hashMapSize10 . collisions ) ;
106+ console . log ( 'hashMapSize10\n' , hashMapSize10 . buckets ) ;
107+ /*
108+ bucket#0: [ { key: 'cat', value: 2 }, { key: 'art', value: 8 } ],
109+ <4 empty items>,
110+ bucket#5: [ { key: 'rat', value: 7 } ],
111+ <1 empty item>,
112+ bucket#7: [ { key: 'dog', value: 1 } ],
113+ <2 empty items> ]
114+ */
115+
116+
117+ //
118+
119+
120+ const hashMapSize100 = new HashMap ( 100 ) ;
121+
122+ hashMapSize100 . set ( 'cat' , 2 ) ;
123+ hashMapSize100 . set ( 'rat' , 7 ) ;
124+ hashMapSize100 . set ( 'dog' , 1 ) ;
125+ hashMapSize100 . set ( 'art' , 8 ) ;
126+
127+ console . log ( 'collisions: ' , hashMapSize100 . collisions ) ;
128+ console . log ( 'hashMapSize100\n' , hashMapSize100 . buckets ) ;
0 commit comments