0
# Java Collection Conversion
1
2
Utilities for seamless conversion between Scala and Java collections. Provides both implicit extension methods for Scala code and explicit conversion methods for Java interoperability.
3
4
## Capabilities
5
6
### Implicit Conversions (Scala-Centric)
7
8
Extension methods that add `.asScala` and `.asJava` to collections for convenient conversion in Scala code.
9
10
```scala { .api }
11
import scala.jdk.CollectionConverters._
12
13
// Extension methods available on Java collections
14
implicit class IteratorHasAsScala[A](i: ju.Iterator[A]) {
15
def asScala: Iterator[A]
16
}
17
18
implicit class EnumerationHasAsScala[A](e: ju.Enumeration[A]) {
19
def asScala: Iterator[A]
20
}
21
22
implicit class IterableHasAsScala[A](i: jl.Iterable[A]) {
23
def asScala: Iterable[A]
24
}
25
26
implicit class CollectionHasAsScala[A](c: ju.Collection[A]) {
27
def asScala: Iterable[A]
28
}
29
30
implicit class ListHasAsScala[A](l: ju.List[A]) {
31
def asScala: mutable.Buffer[A]
32
}
33
34
implicit class SetHasAsScala[A](s: ju.Set[A]) {
35
def asScala: mutable.Set[A]
36
}
37
38
implicit class MapHasAsScala[K, V](m: ju.Map[K, V]) {
39
def asScala: mutable.Map[K, V]
40
}
41
42
implicit class ConcurrentMapHasAsScala[K, V](m: juc.ConcurrentMap[K, V]) {
43
def asScala: concurrent.Map[K, V]
44
}
45
46
implicit class DictionaryHasAsScala[K, V](d: ju.Dictionary[K, V]) {
47
def asScala: mutable.Map[K, V]
48
}
49
50
implicit class PropertiesHasAsScala(p: ju.Properties) {
51
def asScala: mutable.Map[String, String]
52
}
53
54
// Extension methods available on Scala collections
55
implicit class IteratorHasAsJava[A](i: Iterator[A]) {
56
def asJava: ju.Iterator[A]
57
}
58
59
implicit class IterableHasAsJava[A](i: Iterable[A]) {
60
def asJava: jl.Iterable[A]
61
}
62
63
implicit class BufferHasAsJava[A](b: mutable.Buffer[A]) {
64
def asJava: ju.List[A]
65
}
66
67
implicit class MutableSeqHasAsJava[A](s: mutable.Seq[A]) {
68
def asJava: ju.List[A]
69
}
70
71
implicit class SeqHasAsJava[A](s: Seq[A]) {
72
def asJava: ju.List[A]
73
}
74
75
implicit class MutableSetHasAsJava[A](s: mutable.Set[A]) {
76
def asJava: ju.Set[A]
77
}
78
79
implicit class SetHasAsJava[A](s: Set[A]) {
80
def asJava: ju.Set[A]
81
}
82
83
implicit class MutableMapHasAsJava[K, V](m: mutable.Map[K, V]) {
84
def asJava: ju.Map[K, V]
85
}
86
87
implicit class MapHasAsJava[K, V](m: Map[K, V]) {
88
def asJava: ju.Map[K, V]
89
}
90
91
implicit class ConcurrentMapHasAsJava[K, V](m: concurrent.Map[K, V]) {
92
def asJava: juc.ConcurrentMap[K, V]
93
}
94
```
95
96
**Usage Examples:**
97
98
```scala
99
import scala.jdk.CollectionConverters._
100
import java.util.{ArrayList, HashMap, HashSet}
101
import scala.collection.mutable
102
103
// Java to Scala conversion
104
val javaList = new ArrayList[String]()
105
javaList.add("hello")
106
javaList.add("world")
107
val scalaBuffer = javaList.asScala // mutable.Buffer[String]
108
109
val javaMap = new HashMap[String, Int]()
110
javaMap.put("one", 1)
111
javaMap.put("two", 2)
112
val scalaMap = javaMap.asScala // mutable.Map[String, Int]
113
114
// Scala to Java conversion
115
val scalaList = List("a", "b", "c")
116
val javaListFromScala = scalaList.asJava // java.util.List[String]
117
118
val scalaSet = Set(1, 2, 3)
119
val javaSetFromScala = scalaSet.asJava // java.util.Set[Int]
120
121
// Chaining conversions in data processing
122
def processWithJavaLibrary(data: List[String]): List[String] = {
123
val javaResult = someJavaLibrary.process(data.asJava)
124
javaResult.asScala.toList
125
}
126
```
127
128
### Explicit Conversions (Java-Centric)
129
130
Explicit conversion methods designed for use from Java code or when implicit conversions are not desired.
131
132
```scala { .api }
133
import scala.jdk.javaapi.CollectionConverters
134
135
// Java to Scala conversions
136
object CollectionConverters {
137
/**
138
* Convert Java Iterator to Scala Iterator
139
* @param i Java Iterator
140
* @return Scala Iterator
141
*/
142
def asScala[A](i: ju.Iterator[A]): Iterator[A]
143
144
/**
145
* Convert Java Enumeration to Scala Iterator
146
* @param e Java Enumeration
147
* @return Scala Iterator
148
*/
149
def asScala[A](e: ju.Enumeration[A]): Iterator[A]
150
151
/**
152
* Convert Java Iterable to Scala Iterable
153
* @param i Java Iterable
154
* @return Scala Iterable
155
*/
156
def asScala[A](i: jl.Iterable[A]): Iterable[A]
157
158
/**
159
* Convert Java Collection to Scala Iterable
160
* @param c Java Collection
161
* @return Scala Iterable
162
*/
163
def asScala[A](c: ju.Collection[A]): Iterable[A]
164
165
/**
166
* Convert Java List to Scala mutable Buffer
167
* @param l Java List
168
* @return Scala mutable Buffer
169
*/
170
def asScala[A](l: ju.List[A]): mutable.Buffer[A]
171
172
/**
173
* Convert Java Set to Scala mutable Set
174
* @param s Java Set
175
* @return Scala mutable Set
176
*/
177
def asScala[A](s: ju.Set[A]): mutable.Set[A]
178
179
/**
180
* Convert Java Map to Scala mutable Map
181
* @param m Java Map
182
* @return Scala mutable Map
183
*/
184
def asScala[A, B](m: ju.Map[A, B]): mutable.Map[A, B]
185
186
/**
187
* Convert Java ConcurrentMap to Scala concurrent Map
188
* @param m Java ConcurrentMap
189
* @return Scala concurrent Map
190
*/
191
def asScala[A, B](m: juc.ConcurrentMap[A, B]): concurrent.Map[A, B]
192
193
/**
194
* Convert Java Dictionary to Scala mutable Map
195
* @param d Java Dictionary
196
* @return Scala mutable Map
197
*/
198
def asScala[A, B](d: ju.Dictionary[A, B]): mutable.Map[A, B]
199
200
/**
201
* Convert Java Properties to Scala mutable Map
202
* @param p Java Properties
203
* @return Scala mutable Map[String, String]
204
*/
205
def asScala(p: ju.Properties): mutable.Map[String, String]
206
207
// Scala to Java conversions
208
/**
209
* Convert Scala Iterator to Java Iterator
210
* @param i Scala Iterator
211
* @return Java Iterator
212
*/
213
def asJava[A](i: Iterator[A]): ju.Iterator[A]
214
215
/**
216
* Convert Scala Iterable to Java Iterable
217
* @param i Scala Iterable
218
* @return Java Iterable
219
*/
220
def asJava[A](i: Iterable[A]): jl.Iterable[A]
221
222
/**
223
* Convert Scala mutable Buffer to Java List
224
* @param b Scala Buffer
225
* @return Java List
226
*/
227
def asJava[A](b: mutable.Buffer[A]): ju.List[A]
228
229
/**
230
* Convert Scala mutable Seq to Java List
231
* @param s Scala mutable Seq
232
* @return Java List
233
*/
234
def asJava[A](s: mutable.Seq[A]): ju.List[A]
235
236
/**
237
* Convert Scala Seq to Java List
238
* @param s Scala Seq
239
* @return Java List
240
*/
241
def asJava[A](s: Seq[A]): ju.List[A]
242
243
/**
244
* Convert Scala mutable Set to Java Set
245
* @param s Scala mutable Set
246
* @return Java Set
247
*/
248
def asJava[A](s: mutable.Set[A]): ju.Set[A]
249
250
/**
251
* Convert Scala Set to Java Set
252
* @param s Scala Set
253
* @return Java Set
254
*/
255
def asJava[A](s: Set[A]): ju.Set[A]
256
257
/**
258
* Convert Scala mutable Map to Java Map
259
* @param m Scala mutable Map
260
* @return Java Map
261
*/
262
def asJava[K, V](m: mutable.Map[K, V]): ju.Map[K, V]
263
264
/**
265
* Convert Scala Map to Java Map
266
* @param m Scala Map
267
* @return Java Map
268
*/
269
def asJava[K, V](m: Map[K, V]): ju.Map[K, V]
270
271
/**
272
* Convert Scala concurrent Map to Java ConcurrentMap
273
* @param m Scala concurrent Map
274
* @return Java ConcurrentMap
275
*/
276
def asJava[K, V](m: concurrent.Map[K, V]): juc.ConcurrentMap[K, V]
277
}
278
```
279
280
**Usage Examples:**
281
282
```scala
283
import scala.jdk.javaapi.CollectionConverters
284
import java.util.{ArrayList, HashMap}
285
286
// Explicit conversions (useful in Java interop scenarios)
287
val javaList = new ArrayList[String]()
288
val scalaBuffer = CollectionConverters.asScala(javaList)
289
290
val scalaList = List("a", "b", "c")
291
val javaListExplicit = CollectionConverters.asJava(scalaList)
292
293
// In Java code, these methods are easily accessible:
294
// scala.jdk.javaapi.CollectionConverters.asJava(scalaCollection)
295
```
296
297
### Conversion Patterns
298
299
**Working with Java Libraries:**
300
301
```scala
302
import scala.jdk.CollectionConverters._
303
import java.util.concurrent.ConcurrentHashMap
304
305
class ScalaServiceWithJavaCache {
306
private val javaCache = new ConcurrentHashMap[String, String]()
307
308
def put(key: String, value: String): Unit = {
309
javaCache.put(key, value)
310
}
311
312
def getAll: Map[String, String] = {
313
javaCache.asScala.toMap // Convert to immutable Scala Map
314
}
315
316
def processKeys(processor: String => String): Unit = {
317
javaCache.asScala.keys.foreach { key =>
318
val newValue = processor(key)
319
javaCache.put(key, newValue)
320
}
321
}
322
}
323
```
324
325
**Streaming and Processing:**
326
327
```scala
328
import scala.jdk.CollectionConverters._
329
import java.util.stream.Collectors
330
331
def processJavaStream[T](javaList: ju.List[T],
332
filter: T => Boolean,
333
transform: T => String): List[String] = {
334
javaList.stream()
335
.filter(filter(_))
336
.map(transform(_))
337
.collect(Collectors.toList())
338
.asScala
339
.toList
340
}
341
342
// Alternative using Scala collections
343
def processWithScalaCollections[T](javaList: ju.List[T],
344
filter: T => Boolean,
345
transform: T => String): List[String] = {
346
javaList.asScala
347
.filter(filter)
348
.map(transform)
349
.toList
350
}
351
```
352
353
**Configuration and Properties:**
354
355
```scala
356
import scala.jdk.CollectionConverters._
357
import java.util.Properties
358
359
class ConfigurationManager {
360
private val props = new Properties()
361
362
def loadFromJavaProperties(javaProps: Properties): Unit = {
363
// Convert to Scala Map for easier processing
364
val scalaConfig = javaProps.asScala
365
366
scalaConfig.foreach { case (key, value) =>
367
val processedValue = processConfigValue(key, value)
368
props.setProperty(key, processedValue)
369
}
370
}
371
372
def getConfigAsScalaMap: Map[String, String] = {
373
props.asScala.toMap
374
}
375
376
private def processConfigValue(key: String, value: String): String = {
377
// Process configuration values using Scala string methods
378
value.trim.toLowerCase
379
}
380
}
381
```
382
383
**Integration with Java Frameworks:**
384
385
```scala
386
import scala.jdk.CollectionConverters._
387
388
// Example: Working with Java collection-based APIs
389
class DatabaseService {
390
def findUsersByIds(userIds: Set[Long]): List[User] = {
391
// Java database library expects java.util.Set
392
val javaUserIds = userIds.asJava
393
val javaResults = databaseLibrary.findByIds(javaUserIds)
394
395
// Convert results back to Scala collections
396
javaResults.asScala.toList
397
}
398
399
def saveUsers(users: List[User]): Boolean = {
400
val javaUsers = users.asJava
401
databaseLibrary.saveAll(javaUsers)
402
}
403
}
404
```
405
406
### Performance Considerations
407
408
**View-Based Conversions:**
409
410
The conversion methods create views rather than copying data, making them efficient for large collections:
411
412
```scala
413
import scala.jdk.CollectionConverters._
414
415
val largeScalaList = (1 to 1000000).toList
416
val javaView = largeScalaList.asJava // No copying, creates a view
417
418
// Modifications to the original affect the view
419
val mutableBuffer = scala.collection.mutable.Buffer(1, 2, 3)
420
val javaList = mutableBuffer.asJava
421
mutableBuffer += 4
422
// javaList now also contains 4
423
```
424
425
**Bulk Operations:**
426
427
For operations that need to process entire collections, consider converting once rather than per-element:
428
429
```scala
430
import scala.jdk.CollectionConverters._
431
432
// Efficient: Convert once
433
def processEfficiently(javaList: ju.List[String]): List[String] = {
434
javaList.asScala
435
.filter(_.nonEmpty)
436
.map(_.toUpperCase)
437
.toList
438
}
439
440
// Less efficient: Multiple conversions
441
def processInefficiently(javaList: ju.List[String]): ju.List[String] = {
442
javaList.asScala
443
.filter(_.nonEmpty)
444
.map(_.toUpperCase)
445
.asJava
446
}
447
```