0
# Collections Framework
1
2
Scala's collections library adapted for JavaScript with optimized implementations and JavaScript-specific performance characteristics, maintaining full API compatibility while providing efficient JavaScript runtime integration.
3
4
## Capabilities
5
6
### Collection Hierarchy
7
8
The Scala.js collections framework maintains the same type hierarchy as the JVM version while using JavaScript-optimized implementations.
9
10
```scala { .api }
11
/**
12
* Root trait for all collections
13
* Provides basic iteration and transformation operations
14
*/
15
trait Iterable[+A] {
16
/** Iterator over collection elements */
17
def iterator: Iterator[A]
18
19
/** Apply function to each element */
20
def foreach[U](f: A => U): Unit
21
22
/** Transform each element */
23
def map[B](f: A => B): Iterable[B]
24
25
/** Filter elements by predicate */
26
def filter(p: A => Boolean): Iterable[A]
27
28
/** Fold left with accumulator */
29
def foldLeft[B](z: B)(op: (B, A) => B): B
30
31
/** Check if collection is empty */
32
def isEmpty: Boolean
33
34
/** Get collection size */
35
def size: Int
36
37
/** Convert to List */
38
def toList: List[A]
39
40
/** Convert to Array */
41
def toArray[B >: A: ClassTag]: Array[B]
42
}
43
44
/**
45
* Collections that can be traversed multiple times
46
*/
47
trait Traversable[+A] extends Iterable[A] {
48
/** Partition elements by predicate */
49
def partition(p: A => Boolean): (Iterable[A], Iterable[A])
50
51
/** Group elements by key function */
52
def groupBy[K](f: A => K): Map[K, Iterable[A]]
53
54
/** Find first element matching predicate */
55
def find(p: A => Boolean): Option[A]
56
57
/** Test if any element matches predicate */
58
def exists(p: A => Boolean): Boolean
59
60
/** Test if all elements match predicate */
61
def forall(p: A => Boolean): Boolean
62
}
63
```
64
65
### Immutable Collections
66
67
Core immutable collection types optimized for JavaScript runtime performance.
68
69
```scala { .api }
70
/**
71
* Immutable singly-linked list - the fundamental Scala collection
72
* Implemented using JavaScript objects for optimal performance
73
*/
74
sealed abstract class List[+A] extends LinearSeq[A] {
75
/** Prepend element (O(1) operation) */
76
def ::[B >: A](elem: B): List[B]
77
78
/** Get head element (throws on empty list) */
79
def head: A
80
81
/** Get tail list (throws on empty list) */
82
def tail: List[A]
83
84
/** Safe head access */
85
def headOption: Option[A]
86
87
/** Test if list is empty */
88
def isEmpty: Boolean
89
90
/** Get list length (O(n) operation) */
91
def length: Int
92
93
/** Reverse list */
94
def reverse: List[A]
95
96
/** Append another list */
97
def :::[B >: A](prefix: List[B]): List[B]
98
99
/** Transform each element */
100
def map[B](f: A => B): List[B]
101
102
/** Filter elements */
103
def filter(p: A => Boolean): List[A]
104
105
/** Fold left */
106
def foldLeft[B](z: B)(op: (B, A) => B): B
107
108
/** Fold right */
109
def foldRight[B](z: B)(op: (A, B) => B): B
110
}
111
112
/**
113
* Non-empty list node
114
*/
115
final case class ::[+A](head: A, tail: List[A]) extends List[A]
116
117
/**
118
* Empty list singleton
119
*/
120
case object Nil extends List[Nothing]
121
122
/**
123
* Factory methods for List creation
124
*/
125
object List {
126
/** Create list from variable arguments */
127
def apply[A](elems: A*): List[A]
128
129
/** Empty list */
130
def empty[A]: List[A] = Nil
131
132
/** Create list filled with element */
133
def fill[A](n: Int)(elem: A): List[A]
134
135
/** Create list by applying function to indices */
136
def tabulate[A](n: Int)(f: Int => A): List[A]
137
138
/** Create list from range */
139
def range(start: Int, end: Int): List[Int]
140
def range(start: Int, end: Int, step: Int): List[Int]
141
}
142
```
143
144
### Mutable Collections
145
146
Mutable collection types that provide efficient in-place modification operations.
147
148
```scala { .api }
149
/**
150
* Resizable array implementation using JavaScript arrays
151
* Provides O(1) append and random access operations
152
*/
153
class ArrayBuffer[A] extends mutable.Buffer[A] {
154
/** Append element to end */
155
def +=(elem: A): this.type
156
157
/** Prepend element to beginning */
158
def +=:(elem: A): this.type
159
160
/** Insert element at index */
161
def insert(n: Int, elems: A*): Unit
162
163
/** Remove element at index */
164
def remove(n: Int): A
165
def remove(n: Int, count: Int): Unit
166
167
/** Get/set element by index */
168
def apply(n: Int): A
169
def update(n: Int, elem: A): Unit
170
171
/** Current size */
172
def length: Int
173
174
/** Clear all elements */
175
def clear(): Unit
176
177
/** Convert to immutable List */
178
def toList: List[A]
179
}
180
181
/**
182
* Hash-based mutable map using JavaScript objects
183
*/
184
class mutable.Map[A, B] extends mutable.MapLike[A, B, mutable.Map[A, B]] {
185
/** Get value by key */
186
def get(key: A): Option[B]
187
188
/** Set key-value pair */
189
def update(key: A, value: B): Unit
190
191
/** Add key-value pair */
192
def +=(kv: (A, B)): this.type
193
194
/** Remove key */
195
def -=(key: A): this.type
196
197
/** Test if key exists */
198
def contains(key: A): Boolean
199
200
/** Get all keys */
201
def keys: Iterable[A]
202
203
/** Get all values */
204
def values: Iterable[B]
205
206
/** Clear all entries */
207
def clear(): Unit
208
209
/** Number of entries */
210
def size: Int
211
}
212
```
213
214
### Immutable Map and Set
215
216
Persistent data structures providing efficient immutable key-value and set operations.
217
218
```scala { .api }
219
/**
220
* Immutable hash-based map
221
* Uses structural sharing for efficient copying
222
*/
223
trait Map[A, +B] extends Iterable[(A, B)] {
224
/** Get value by key */
225
def get(key: A): Option[B]
226
227
/** Get value or default */
228
def getOrElse[B1 >: B](key: A, default: => B1): B1
229
230
/** Add key-value pair (returns new map) */
231
def +[B1 >: B](kv: (A, B1)): Map[A, B1]
232
233
/** Remove key (returns new map) */
234
def -(key: A): Map[A, B]
235
236
/** Test if key exists */
237
def contains(key: A): Boolean
238
239
/** Transform values */
240
def mapValues[C](f: B => C): Map[A, C]
241
242
/** Get all keys */
243
def keys: Iterable[A]
244
245
/** Get all values */
246
def values: Iterable[B]
247
248
/** Number of entries */
249
def size: Int
250
251
/** Test if empty */
252
def isEmpty: Boolean
253
}
254
255
/**
256
* Immutable hash-based set
257
*/
258
trait Set[A] extends Iterable[A] {
259
/** Test if element is in set */
260
def contains(elem: A): Boolean
261
262
/** Add element (returns new set) */
263
def +(elem: A): Set[A]
264
265
/** Remove element (returns new set) */
266
def -(elem: A): Set[A]
267
268
/** Set union */
269
def ++(that: Set[A]): Set[A]
270
271
/** Set intersection */
272
def intersect(that: Set[A]): Set[A]
273
274
/** Set difference */
275
def diff(that: Set[A]): Set[A]
276
277
/** Test if subset */
278
def subsetOf(that: Set[A]): Boolean
279
280
/** Number of elements */
281
def size: Int
282
283
/** Test if empty */
284
def isEmpty: Boolean
285
}
286
```
287
288
**Usage Examples:**
289
290
```scala
291
import scala.collection._
292
293
// List operations
294
val numbers = List(1, 2, 3, 4, 5)
295
val doubled = numbers.map(_ * 2)
296
val evens = numbers.filter(_ % 2 == 0)
297
val sum = numbers.foldLeft(0)(_ + _)
298
299
// List construction
300
val prepended = 0 :: numbers // List(0, 1, 2, 3, 4, 5)
301
val combined = List(1, 2) ::: List(3, 4) // List(1, 2, 3, 4)
302
303
// ArrayBuffer for mutable operations
304
val buffer = mutable.ArrayBuffer[Int]()
305
buffer += 1
306
buffer += 2
307
buffer ++= List(3, 4, 5)
308
buffer.insert(0, 0) // Insert at beginning
309
val removed = buffer.remove(1) // Remove second element
310
311
// Immutable Map operations
312
val scores = Map("Alice" -> 95, "Bob" -> 87, "Carol" -> 92)
313
val updated = scores + ("Dave" -> 88) // Add new entry
314
val withoutBob = scores - "Bob" // Remove entry
315
val aliceScore = scores.getOrElse("Alice", 0)
316
317
// Set operations
318
val fruits = Set("apple", "banana", "cherry")
319
val moreFruits = fruits + "date"
320
val tropical = Set("banana", "mango", "pineapple")
321
val common = fruits intersect tropical // Set("banana")
322
val unique = fruits diff tropical // Set("apple", "cherry")
323
324
// Mutable Map for efficient updates
325
val cache = mutable.Map[String, Int]()
326
cache("key1") = 100
327
cache += ("key2" -> 200)
328
if (cache.contains("key1")) {
329
println(s"Found: ${cache("key1")}")
330
}
331
332
// Collection transformations
333
val words = List("hello", "world", "scala", "js")
334
val lengths = words.map(_.length)
335
val longWords = words.filter(_.length > 4)
336
val grouped = words.groupBy(_.charAt(0))
337
338
// Advanced operations
339
val nested = List(List(1, 2), List(3, 4), List(5))
340
val flattened = nested.flatten // List(1, 2, 3, 4, 5)
341
342
val pairs = List(1, 2, 3).zip(List("a", "b", "c")) // List((1,"a"), (2,"b"), (3,"c"))
343
val (odds, evens2) = List(1, 2, 3, 4, 5).partition(_ % 2 == 1)
344
```
345
346
### Iterator and Stream Operations
347
348
Lazy evaluation and streaming operations for efficient large data processing.
349
350
```scala { .api }
351
/**
352
* Iterator providing lazy traversal of collections
353
* Consumes elements on-demand for memory efficiency
354
*/
355
trait Iterator[+A] {
356
/** Test if more elements available */
357
def hasNext: Boolean
358
359
/** Get next element (consuming) */
360
def next(): A
361
362
/** Transform elements lazily */
363
def map[B](f: A => B): Iterator[B]
364
365
/** Filter elements lazily */
366
def filter(p: A => Boolean): Iterator[A]
367
368
/** Take first n elements */
369
def take(n: Int): Iterator[A]
370
371
/** Drop first n elements */
372
def drop(n: Int): Iterator[A]
373
374
/** Convert to List (materializes all elements) */
375
def toList: List[A]
376
377
/** Fold left over elements */
378
def foldLeft[B](z: B)(op: (B, A) => B): B
379
380
/** Apply function to each element (consuming) */
381
def foreach[U](f: A => U): Unit
382
}
383
384
/**
385
* Lazy list with memoization (Scala 2.13+)
386
* Elements computed on-demand and cached
387
*/
388
class LazyList[+A] extends LinearSeq[A] {
389
/** Get head element (computed lazily) */
390
def head: A
391
392
/** Get tail (computed lazily) */
393
def tail: LazyList[A]
394
395
/** Test if empty */
396
def isEmpty: Boolean
397
398
/** Prepend element */
399
def #::[B >: A](elem: B): LazyList[B]
400
401
/** Transform elements (lazy) */
402
def map[B](f: A => B): LazyList[B]
403
404
/** Filter elements (lazy) */
405
def filter(p: A => Boolean): LazyList[A]
406
407
/** Take elements (lazy) */
408
def take(n: Int): LazyList[A]
409
410
/** Drop elements (lazy) */
411
def drop(n: Int): LazyList[A]
412
}
413
414
/**
415
* Factory methods for LazyList
416
*/
417
object LazyList {
418
/** Create LazyList from elements */
419
def apply[A](elems: A*): LazyList[A]
420
421
/** Empty LazyList */
422
def empty[A]: LazyList[A]
423
424
/** Create infinite sequence */
425
def continually[A](elem: => A): LazyList[A]
426
427
/** Create sequence by iterating function */
428
def iterate[A](start: A)(f: A => A): LazyList[A]
429
430
/** Create sequence from range */
431
def range(start: Int, end: Int): LazyList[Int]
432
def range(start: Int, end: Int, step: Int): LazyList[Int]
433
434
/** Create from iterator */
435
def from(iterator: Iterator[A]): LazyList[A]
436
}
437
```
438
439
**Usage Examples:**
440
441
```scala
442
// Iterator for memory-efficient processing
443
val largeData = (1 to 1000000).iterator
444
val processed = largeData
445
.filter(_ % 2 == 0)
446
.map(_ * 2)
447
.take(100)
448
.toList
449
450
// LazyList for infinite sequences
451
val fibonacci: LazyList[Int] = 0 #:: 1 #:: fibonacci.zip(fibonacci.tail).map { case (a, b) => a + b }
452
val first10Fib = fibonacci.take(10).toList
453
454
// Lazy evaluation benefits
455
val expensiveOperation = LazyList.continually {
456
println("Computing...") // Only printed when accessed
457
scala.util.Random.nextInt(100)
458
}
459
460
val firstThree = expensiveOperation.take(3).toList // Prints "Computing..." 3 times
461
462
// Stream processing pipeline
463
val numbers = LazyList.range(1, 1000000)
464
val result = numbers
465
.filter(_ % 3 == 0)
466
.map(n => n * n)
467
.takeWhile(_ < 10000)
468
.sum // Only computes what's needed
469
```