0
# Collections & Data Structures
1
2
Specialized collection types including case-insensitive maps, concurrent collections, and caching utilities for efficient data handling in Ktor applications.
3
4
## Capabilities
5
6
### Case-Insensitive Collections
7
8
Collections that handle string keys in a case-insensitive manner, useful for HTTP headers and similar use cases.
9
10
```kotlin { .api }
11
/**
12
* Create an instance of case-insensitive mutable map
13
*/
14
fun <Value : Any> caseInsensitiveMap(): MutableMap<String, Value>
15
16
/**
17
* A map with case-insensitive String keys
18
*/
19
class CaseInsensitiveMap<Value : Any> : MutableMap<String, Value> {
20
override val size: Int
21
override fun containsKey(key: String): Boolean
22
override fun containsValue(value: Value): Boolean
23
override fun get(key: String): Value?
24
override fun isEmpty(): Boolean
25
override fun clear()
26
override fun put(key: String, value: Value): Value?
27
override fun putAll(from: Map<out String, Value>)
28
override fun remove(key: String): Value?
29
override val keys: MutableSet<String>
30
override val entries: MutableSet<MutableMap.MutableEntry<String, Value>>
31
override val values: MutableCollection<Value>
32
}
33
```
34
35
**Usage Examples:**
36
37
```kotlin
38
import io.ktor.util.*
39
40
// Create case-insensitive map
41
val headers = caseInsensitiveMap<String>()
42
43
// Keys are case-insensitive
44
headers["Content-Type"] = "application/json"
45
headers["content-type"] = "text/plain" // Overwrites previous value
46
headers["CONTENT-TYPE"] = "text/html" // Overwrites again
47
48
println(headers["Content-Type"]) // "text/html"
49
println(headers["content-type"]) // "text/html"
50
println(headers["CONTENT-TYPE"]) // "text/html"
51
52
// Direct instantiation
53
val customMap = CaseInsensitiveMap<Int>()
54
customMap["Hello"] = 1
55
customMap["HELLO"] = 2
56
customMap["hello"] = 3
57
58
println(customMap.size) // 1 (all keys are the same)
59
println(customMap["Hello"]) // 3
60
```
61
62
### Concurrent Collections
63
64
Thread-safe collection implementations for concurrent access patterns (expect/actual implementations).
65
66
```kotlin { .api }
67
/**
68
* Ktor concurrent map implementation (expect/actual)
69
*/
70
expect class ConcurrentMap<Key, Value>(
71
initialCapacity: Int = INITIAL_CAPACITY
72
) : MutableMap<Key, Value> {
73
74
/** Computes block and inserts result in map. The block will be evaluated at most once. */
75
fun computeIfAbsent(key: Key, block: () -> Value): Value
76
77
/** Removes key from map if it is mapped to value */
78
fun remove(key: Key, value: Value): Boolean
79
80
// Standard MutableMap operations
81
override fun remove(key: Key): Value?
82
override fun clear()
83
override fun put(key: Key, value: Value): Value?
84
override fun putAll(from: Map<out Key, Value>)
85
override val entries: MutableSet<MutableMap.MutableEntry<Key, Value>>
86
override val keys: MutableSet<Key>
87
override val values: MutableCollection<Value>
88
override fun containsKey(key: Key): Boolean
89
override fun containsValue(value: Value): Boolean
90
override fun get(key: Key): Value?
91
override fun isEmpty(): Boolean
92
override val size: Int
93
}
94
```
95
96
**Usage Examples:**
97
98
```kotlin
99
import io.ktor.util.collections.*
100
101
// Create concurrent map with custom initial capacity
102
val cache = ConcurrentMap<String, ExpensiveObject>(64)
103
104
// Thread-safe lazy computation
105
val result = cache.computeIfAbsent("key1") {
106
// This block will be executed at most once, even with concurrent access
107
ExpensiveObject.create()
108
}
109
110
// Thread-safe conditional removal
111
val wasRemoved = cache.remove("key1", result) // Only removes if mapped to 'result'
112
113
// Standard map operations are thread-safe
114
cache["key2"] = AnotherObject()
115
val value = cache["key2"]
116
117
// Use in concurrent scenarios
118
val concurrentCache = ConcurrentMap<Int, String>()
119
120
// Multiple threads can safely access
121
Thread {
122
concurrentCache.computeIfAbsent(1) { "Thread 1 value" }
123
}.start()
124
125
Thread {
126
concurrentCache.computeIfAbsent(1) { "Thread 2 value" }
127
}.start()
128
129
// Only one of the blocks will execute
130
```
131
132
### Set Utilities
133
134
Utilities for working with sets including platform-specific immutability support.
135
136
```kotlin { .api }
137
/**
138
* Freeze selected set. May do nothing on some platforms (expect/actual)
139
*/
140
expect fun <T> Set<T>.unmodifiable(): Set<T>
141
```
142
143
**Usage Examples:**
144
145
```kotlin
146
import io.ktor.util.*
147
148
// Create mutable set and make it unmodifiable
149
val mutableSet = mutableSetOf("apple", "banana", "cherry")
150
val immutableSet = mutableSet.unmodifiable()
151
152
// immutableSet is now read-only (platform-dependent implementation)
153
// Attempts to modify will throw exceptions on platforms that support it
154
155
// Use with collections that need to be frozen
156
val configuredOptions = setOf("option1", "option2", "option3").unmodifiable()
157
```
158
159
### JVM-Specific Collections
160
161
Additional collection utilities available specifically on the JVM platform.
162
163
```kotlin { .api }
164
/**
165
* Create a new instance of thread safe LRU cache (JVM only)
166
*/
167
fun <K, V> createLRUCache(
168
supplier: (K) -> V,
169
close: (V) -> Unit,
170
maxSize: Int
171
): Map<K, V>
172
```
173
174
**Usage Examples:**
175
176
```kotlin
177
import io.ktor.util.*
178
179
// Create LRU cache with supplier and cleanup functions (JVM only)
180
val imageCache = createLRUCache<String, BufferedImage>(
181
supplier = { path -> loadImageFromDisk(path) },
182
close = { image -> image.flush() },
183
maxSize = 100
184
)
185
186
// Cache automatically manages size and calls cleanup
187
val image1 = imageCache["image1.png"] // Loads from disk
188
val image2 = imageCache["image1.png"] // Returns cached version
189
val image3 = imageCache["image2.png"] // Loads from disk
190
191
// When cache exceeds maxSize, oldest entries are removed and close() is called
192
```
193
194
## Implementation Notes
195
196
- **Platform Support**: Case-insensitive collections are available on all platforms (Common)
197
- **Concurrent Collections**: ConcurrentMap uses expect/actual pattern with platform-specific implementations
198
- JVM: Uses Java's concurrent collections
199
- Native: Platform-specific thread-safe implementations
200
- JS: May use simpler implementations since JS is single-threaded
201
- **Thread Safety**: ConcurrentMap provides thread-safe operations, CaseInsensitiveMap does not
202
- **LRU Cache**: Only available on JVM platform, uses synchronized LinkedHashMap internally
203
- **Memory Management**: LRU cache supports automatic cleanup of evicted entries
204
- **Case Sensitivity**: CaseInsensitiveMap treats keys like "Content-Type", "content-type", and "CONTENT-TYPE" as identical