2. An Example
package com.inphina.collections.person
class Person(val name: String, val age: Int) {
}
Somewhere in the code:
val (minors, adults) = people partition (_.age < 18)
Three concepts:
- Simple pattern matching
- An Infix method call
- A function value
4. Collection Properties
Object-oriented
Generic: List[T], Map[K, V]
optionally persistent: scala.collections.immutable
Higher-order with methods like foreach, map, filter
uniform return type principle: operations return
collections of same type as their left operand
5. The Uniform Return Type Principle
Bulk operations return collections of the same type (constructor) as
their left operand.
scala> val ys = List(1,2,3)
ys: List[Int] = List(1, 2, 3)
scala> val xs: Seq[Int] = ys
xs: Seq[Int] = List(1, 2, 3)
scala> xs map(_ + 1)
res0: Seq[Int] = List(2, 3, 4)
scala> ys map(_ + 1)
res1: List[Int] = List(2, 3, 4)
6. Using Collections: Map and Filter
scala> val xs = List(1, 2, 3)
xs: List[Int] = List(1, 2, 3)
scala> val ys = xs map (x => x + 1)
ys: List[Int] = List(2, 3, 4)
scala> val ys = xs map (_ + 1)
ys: List[Int] = List(2, 3, 4)
scala> val zs = ys filter (_ % 2 == 0)
zs: List[Int] = List(2 , 4)
scala> val as = ys map (0 to _)
as: List[scala.collection.immutable.Range.Inclusive] =
List(Range(0, 1), Range(0, 1, 2), Range(0, 1, 2, 3))
7. Using Collections: flatMap and groupBy
scala> val bs = as.flatten
bs: List[Int] = List(0, 1, 0, 1, 2, 0, 1, 2, 3)
scala> val bs = ys flatMap (0 to _)
bs: List[Int] = List(0, 1, 0, 1, 2, 0, 1, 2, 3)
scala> val fruit = Vector("apples", "oranges", "ananas")
fruit: scala.collection.immutable.Vector[java.lang.String] =
Vector(apples, oranges, ananas)
scala> fruit groupBy (_.head)
res3:
scala.collection.immutable.Map[Char,scala.collection.immutable.Ve
ctor[java.lang.String]] = Map(a -> Vector(apples, ananas), o ->
Vector(oranges))
8. Using Collections: For Notation
scala> for (x <- xs) yield x + 1 // map
res7: Seq[Int] = List(2, 3, 4)
scala> for (x <- res7 if x % 2 == 0 ) yield x // filter
res8: Seq[Int] = List(2, 4)
scala> for (x <- xs; y <- 0 to x) yield y // flatMap
res9: Seq[Int] = List(0, 1, 0, 1, 2, 0, 1, 2, 3)
9. String also a Collection
Even String is also a collection that means we can
apply higher order functions on it.
scala> val aString = "hello world"
aString: java.lang.String = hello world
scala> aString map (_.toUpper)
res12: String = HELLO WORLD
11. Scala Collection Hierarchy
All Collection classes are in scala.collection or one of its sub-
packages mutable, immutable and generic
Root collections in the package scala.collection define the
same interface as immutable collections and mutable
collections add some modification operations to make it
mutable
The generic package contains building block for implementing
Collections.
15. Overview Of Collections
Traversable
Iterable
Seq
IndexedSeq
LinearSeq
mutable.Buffer
Range
Set
SortedSet
immutable.HashSet
mutable.HashSet
mutable.LinkedHashSet
BitSet
Map
SortedMap
immutable.HashMap
mutable.HashMap
mutable.LinkedHashMap
16. Commonality In collections
All classes are quite common. For instance, every
kind of collection can be created by same uniform
Syntax
Traversable(1, 2, 3)
Iterable("x", "y", "z")
Map("x" -> 24, "y" -> 25, "z" -> 26)
Set(Color.red, Color.green, Color.blue)
SortedSet("hello", "world")
Buffer(x, y, z)
IndexedSeq(1.0, 2.0)
LinearSeq(a, b, c)
The same principle applies with specific collection implementations
List(1, 2, 3)
HashMap("x" -> 24, "y" -> 25, "z" -> 26)
17. Commonality In collections...
All these Collections get displayed with toString in the same way
they are written above
All collections support the API provided by Traversable but
specializes types wherever it makes sense
map method in class Traversable returns another Traversable as
its result. But this result type is overridden in subclasses
scala> List(1, 2, 3) map (_ + 1)
res0: List[Int] = List(2, 3, 4)
scala> Set(1, 2, 3) map (_ * 2)
res0: Set[Int] = Set(2, 4, 6)
This behavior in the collections libraries is called the uniform return type principle.
18. Trait Traversable
Top of collection hierarchy. Its abstract method is foreach:
def foreach[U](f: Elem => U)
Traversable also provides lot of concrete methods they fall in
following categories
Addition: ++, appends two traversables together
Map operations: map, flatMap, and collect
Conversions: toArray, toList, toIterable, toSeq, toIndexedSeq, toStream, toSet, toMap,
Copying operations: copyToBuffer and copyToArray
Size info operations: isEmpty, nonEmpty, size, and hasDefiniteSize
Element retrieval operations: head, last, headOption, lastOption, and find
Sub-Collection retrieval operations: tail, init, slice, take, drop, takeWhile,
dropWhile, filter, filterNot, withFilter
Subdivision operations: splitAt, span, partition, groupBy
Element tests: exists, forall, count
Folds: foldLeft, foldRight, /:, :, reduceLeft, reduceRight
Specific Folds: sum, product, min, max
String Operations: mkString, addString, stringPrefix
19. Trait Iterable
This is the next Trait in Collection hierarchy. All methods in this trait
are defined in terms of an abstract method iterator, which returns
collection results one by one.
The foreach method from trait Traversable is implemented in
Iterable in terms of iterator
def foreach[U](f: Elem => U): Unit = {
val it = iterator
while (it.hasNext) f(it.next())
}
20. An Example ..
Task: Phone keys has mnemonics attached to them
val mnemonics = Map(
'2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL", '6' -> "MNO",
'7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ")
Assume that you are given a dictionary dict as a list of words. Design a
class Coder with a method translate such that
new Coder(dict).translate(phoneNumber)
Produces all phrases of words which can serve as mnemonics for the
phone number
Example The phone number “7225276257” should have a mnemonic
Scala rocks
as one element of the list of solution phrases
21. An Example
Creating a mnemonics Map
val mnemonics = Map('2' -> "ABC", '3' -> "DEF", '4' -> "GHI", '5' -> "JKL",
'6' -> "MNO", '7' -> "PQRS", '8' -> "TUV", '9' -> "WXYZ")
Creating reverse map with upper code
val upperCode: Map[Char, Char] = for ((digit, str) <- mnemonics; ltr <- str)
yield (ltr -> digit)
Creating a word for which digit string will be generated
val word = "java"
Gettng a digit string from a word eg; "java" -> "5282"
word.toUpperCase map (upperCode(_))
22. Everything is a library
Collections feel they are language constructs
Language does not contain any collection related
constructs
- no collection types
- no collection literals
- no collection operators
Everything is in library
They are extensible