1
1
package hashtable .design ;
2
2
3
- // TO_START
4
- public class HashMap {
3
+ import java .util .ArrayList ;
4
+ import java .util .LinkedList ;
5
+ import java .util .List ;
6
+ import java .util .Optional ;
7
+ import java .util .stream .Collectors ;
5
8
9
+ class MapEntry <K , V >
10
+ {
11
+ private K key ;
12
+ private V value ;
13
+ public MapEntry ( K key , V value )
14
+ {
15
+ this .key = key ;
16
+ this .value = value ;
17
+ }
18
+
19
+ public K getKey ()
20
+ {
21
+ return key ;
22
+ }
23
+ public V getValue ()
24
+ {
25
+ return value ;
26
+ }
27
+ public void setKey ( K key )
28
+ {
29
+ this .key = key ;
30
+ }
31
+ public void setValue ( V value )
32
+ {
33
+ this .value = value ;
34
+ }
35
+
36
+ @ Override
37
+ public boolean equals ( Object entry )
38
+ {
39
+ // judge entry class type
40
+ if ( !( entry instanceof MapEntry ) )
41
+ {
42
+ return false ;
43
+ }
44
+
45
+ // use the key field as standard
46
+ MapEntry <K ,V > castedEntry = (MapEntry <K ,V >) entry ;
47
+ return this .getKey ().equals (castedEntry .getKey ());
48
+ }
49
+
50
+ @ Override
51
+ public int hashCode ()
52
+ {
53
+ return this .getKey ().hashCode ();
54
+ }
6
55
}
56
+
57
+ public class HashMap <K ,V >
58
+ {
59
+ private int bucketSize ;
60
+ private List <List <MapEntry <K ,V >>> listHeads ;
61
+
62
+ public HashMap ( int bucketSize )
63
+ {
64
+ this .bucketSize = bucketSize ;
65
+ listHeads = new ArrayList <>();
66
+ for (int i = 0 ; i < bucketSize ; i ++)
67
+ {
68
+ listHeads .add ( new LinkedList <MapEntry <K ,V >>());
69
+ }
70
+ }
71
+
72
+ private int calcBucketIndex ( K key )
73
+ {
74
+ return key .hashCode () % bucketSize ;
75
+ }
76
+
77
+ private List <MapEntry <K ,V >> getMatchedEntry ( final K key )
78
+ {
79
+ return listHeads .get ( calcBucketIndex ( key ) )
80
+ .stream ()
81
+ .filter ( ( MapEntry <K , V > o ) -> o .getKey ().equals (key ) )
82
+ .collect ( Collectors .toList () );
83
+ }
84
+
85
+ public Optional <V > get ( final K key )
86
+ {
87
+ List <MapEntry <K ,V >> matchedEntry = getMatchedEntry ( key );
88
+ if ( matchedEntry .size () == 0 )
89
+ {
90
+ return Optional .empty ();
91
+ }
92
+ else if ( matchedEntry .size () == 1 )
93
+ {
94
+ return Optional .ofNullable ( matchedEntry .get ( 0 ).getValue () );
95
+ }
96
+ else
97
+ {
98
+ throw new IllegalStateException ("" );
99
+ }
100
+ }
101
+
102
+ public Optional <V > put ( final K key , final V value )
103
+ {
104
+ List <MapEntry <K ,V >> matchedEntry = getMatchedEntry ( key );
105
+ if ( matchedEntry .size () == 0 )
106
+ {
107
+ int bucketIndex = calcBucketIndex ( key );
108
+ List <MapEntry <K ,V >> chainingList = listHeads .get (bucketIndex );
109
+ chainingList .add ( new MapEntry <K ,V >( key , value ));
110
+ return Optional .ofNullable (value );
111
+ }
112
+ else if ( matchedEntry .size () == 1 )
113
+ {
114
+ matchedEntry .get ( 0 )
115
+ .setValue ( value );
116
+ return Optional .ofNullable (value );
117
+ }
118
+ else
119
+ {
120
+ throw new IllegalStateException ("" );
121
+ }
122
+ }
123
+
124
+ public Optional <V > remove ( final K key )
125
+ {
126
+ int bucketIndex = calcBucketIndex ( key );
127
+
128
+
129
+ List <MapEntry <K ,V >> chainingList = listHeads .get ( bucketIndex );
130
+ int valueIndex = chainingList .indexOf ( key );
131
+ if ( valueIndex == -1 )
132
+ {
133
+ return null ;
134
+ }
135
+ else
136
+ {
137
+ MapEntry <K ,V > entry = chainingList .get ( valueIndex );
138
+ if ( entry != null )
139
+ {
140
+ V entryValue = (V ) (entry .getValue ());
141
+ chainingList .remove ( entry );
142
+ return Optional .ofNullable (entryValue );
143
+ }
144
+ else
145
+ {
146
+ return Optional .empty ();
147
+ }
148
+ }
149
+ }
150
+ }
0 commit comments