@@ -3,60 +3,207 @@ package com.github.contest.hashTable.customStructure
3
3
import java.util.concurrent.locks.ReentrantLock
4
4
import kotlin.concurrent.withLock
5
5
6
- class CustomConcurrentHashMap <T > {
7
-
8
-
9
- }
10
-
11
6
12
7
class MyConcurrentHashMap <K , V >(private val segmentCount : Int = 16 ) {
13
8
9
+ private class HashEntry <K , V >(val key : K , var value : V , var next : HashEntry <K , V >? )
10
+
14
11
private class Segment <K , V > {
15
- val entries = mutableListOf<Entry <K , V >>()
16
12
val lock = ReentrantLock ()
13
+ var table: Array <HashEntry <K , V >? > = arrayOfNulls(16 )
14
+ var count = 0
17
15
18
16
fun get (key : K ): V ? = lock.withLock {
19
- entries.find { it.key == key }?.value
17
+ val hash = key.hashCode()
18
+ val index = hash % table.size
19
+ var entry = table[index]
20
+ while (entry != null ) {
21
+ if (entry.key == key) {
22
+ return entry.value
23
+ }
24
+ entry = entry.next
25
+ }
26
+ return null
20
27
}
21
28
22
29
fun put (key : K , value : V ): V ? = lock.withLock {
23
- entries.find { it.key == key }?.let {
24
- val oldValue = it.value
25
- it.value = value
26
- oldValue
27
- } ? : run {
28
- entries.add(Entry (key, value))
29
- null
30
+ val hash = key.hashCode()
31
+ val index = hash % table.size
32
+ var entry = table[index]
33
+ while (entry != null ) {
34
+ if (entry.key == key) {
35
+ val oldValue = entry.value
36
+ entry.value = value
37
+ return oldValue
38
+ }
39
+ entry = entry.next
40
+ }
41
+ val newEntry = HashEntry (key, value, table[index])
42
+ table[index] = newEntry
43
+ count++
44
+ if (count >= table.size * 0.75 ) {
45
+ rehash()
30
46
}
47
+ return null
31
48
}
32
49
33
50
fun remove (key : K ): V ? = lock.withLock {
34
- entries.find { it.key == key }?.let {
35
- entries.remove(it)
36
- it.value
51
+ val hash = key.hashCode()
52
+ val index = hash % table.size
53
+ var entry = table[index]
54
+ var prev: HashEntry <K , V >? = null
55
+ while (entry != null ) {
56
+ if (entry.key == key) {
57
+ if (prev == null ) {
58
+ table[index] = entry.next
59
+ } else {
60
+ prev.next = entry.next
61
+ }
62
+ count--
63
+ return entry.value
64
+ }
65
+ prev = entry
66
+ entry = entry.next
37
67
}
68
+ return null
38
69
}
39
70
40
- fun size (): Int = lock.withLock { entries.size }
71
+ private fun rehash () {
72
+ val oldTable = table
73
+ val newTableSize = table.size * 2
74
+ table = arrayOfNulls(newTableSize)
75
+ count = 0
76
+ for (entry in oldTable) {
77
+ var current = entry
78
+ while (current != null ) {
79
+ put(current.key, current.value)
80
+ current = current.next
81
+ }
82
+ }
83
+ }
84
+ }
41
85
42
- fun clear () = lock.withLock { entries.clear() }
86
+ private val segments: Array <Segment <K , V >> = Array (segmentCount) { Segment () }
87
+
88
+ private fun getSegment (key : K ): Segment <K , V > {
89
+ val hash = key.hashCode()
90
+ val index = (hash ushr 16 ) % segmentCount
91
+ return segments[index]
43
92
}
44
93
45
- private data class Entry < K , V >( val key : K , var value : V )
94
+ fun get ( key : K ) : V ? = getSegment(key).get(key )
46
95
47
- private val segments: Array <Segment <K , V >> = Array (segmentCount) { Segment () }
96
+ fun put (key : K , value : V ): V ? = getSegment(key).put(key, value)
97
+
98
+ fun remove (key : K ): V ? = getSegment(key).remove(key)
99
+ }
100
+
101
+
102
+ class CustomConcurrentHashMap <K , V >(private val capacitySegments : Int = 16 ) {
103
+
104
+ private data class HashEntry <K , V >(val key : K , var value : V , var next : HashEntry <K , V >? )
105
+
106
+
107
+ private class Segment <K , V > {
108
+
109
+ private val lock = ReentrantLock ()
110
+ private var table: Array <HashEntry <K , V >? > = arrayOfNulls(16 )
111
+ private var count = 0
112
+
113
+ fun put (key : K , value : V ): V ? = lock.withLock {
114
+ val hash = key.hashCode()
115
+ val index = hash % table.size
116
+ var entry = table[index]
117
+ while (entry != null ) {
118
+ if (entry.key == key) {
119
+ val oldValue = entry.value
120
+ entry.value = value
121
+ return oldValue
122
+ }
123
+ entry = entry.next
124
+ }
125
+ entry = table[index]
126
+ val newEntry = HashEntry (key, value, table[index])
127
+ table[index] = newEntry
128
+ count++
129
+ if (count >= table.size * 0.75 ) rehash()
130
+ return null
131
+ }
132
+
133
+
134
+ fun get (key : K ): V ? {
135
+ val hash = key.hashCode()
136
+ val index = hash % table.size
137
+ var entry = table[index]
138
+ while (entry != null ) {
139
+ if (entry.key == key) return entry.value
140
+ entry = entry.next
141
+ }
142
+
143
+ return null
144
+ }
145
+
146
+ fun remove (key : K ): V ? = lock.withLock {
147
+ val hash = key.hashCode()
148
+ val index = hash % table.size
149
+ var entry = table[index]
150
+ var prev: HashEntry <K , V >? = null
151
+ while (entry != null ) {
152
+ if (entry.key == key) {
153
+ if (prev == null ) {
154
+ table[index] = entry.next
155
+ } else prev.next = entry.next
156
+ count--
157
+ return entry.value
158
+ }
159
+ prev = entry
160
+ entry = entry.next
161
+ }
162
+
163
+ return null
164
+ }
48
165
49
- private fun getSegmentIndex (key : K ): Int = key.hashCode().let { Math .abs(it % segmentCount) }
50
166
51
- fun get (key : K ): V ? = segments[getSegmentIndex(key)].get(key)
167
+ private fun rehash () {
168
+ val oldTable = table
169
+ val newSize = table.size * 2
170
+ table = arrayOfNulls(newSize)
171
+ count = 0
172
+ for (entry in oldTable) {
173
+ var current = entry
174
+ while (current != null ) {
175
+ put(current.key, current.value)
176
+ current = current.next
177
+ }
178
+ }
179
+ }
52
180
53
- fun put ( key : K , value : V ): V ? = segments[getSegmentIndex(key)].put(key, value)
181
+ }
54
182
55
- fun remove ( key : K ): V ? = segments[getSegmentIndex(key)].remove(key)
183
+ private val segments = Array < Segment < K , V >>(capacitySegments) { Segment () }
56
184
57
- fun size (): Int = segments.sumOf { it.size( ) }
185
+ fun put ( key : K , value : V ) = getSegment(key). let { it.put(key, value ) }
58
186
59
- fun clear () {
60
- segments.forEach { it.clear() }
187
+ fun get (key : K ): V ? = getSegment(key).let { it.get(key) }
188
+
189
+ private fun getSegment (key : K ): Segment <K , V > {
190
+ val hash = key.hashCode()
191
+ val index = (hash ushr 16 ) % capacitySegments
192
+ return segments[index]
61
193
}
62
- }
194
+
195
+
196
+ }
197
+
198
+
199
+
200
+
201
+
202
+
203
+
204
+
205
+
206
+
207
+
208
+
209
+
0 commit comments