Example #1: Read from a list & write to a list
Java Way in Scala
1 2 3 4 5 6 7 8 9 10 11 12 13 | object ListToList extends App { val inputList = List("Java", "Scala", "Ruby") val outputList = scala.collection.mutable.ListBuffer[String](); for(item <- inputList) { outputList += item + " Programming" } println(outputList.toList) } |
Output: List(Java Programming, Scala Programming, Ruby Programming)
Scala Way in Scala: Using the “map” functional combinator
Immutable code as shown below using the “map” function.
1 2 3 4 5 6 7 8 | object ListToList extends App { val inputList = List("Java", "Scala", "Ruby") val outputList = inputList.map(item => item + " programming") println(outputList) //List(Java Programming, Scala Programming, Ruby Programming) } |
Scala Way in Scala: Using recursion
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | object ListToList extends App { val inputList = List("Java", "Scala", "Ruby") def add(xs: List[String]) : List[String] = { xs match { case List() => List[String]() case y :: ys => (y + " Programming") :: add(ys) //recursion } } println(add(inputList)) //List(Java Programming, Scala Programming, Ruby Programming) } |
What does y :: ys mean?
It means head::tail. The head of the list is bound to “y”, and the rest (i.e. the tail) is bound to “ys”.
Example #2: Aggregate a list of values
Java Way by mutating state
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | object AggregateValue extends App { var total = 0 //mutable def sum(input: List[Int]): Int = { for (num <- input) { total += num } total } println(sum(List(1,2,3)))// 6 } |
Scala Way in Scala using the “foldLeft” functional combinator
1 2 3 4 5 6 7 8 9 10 11 | object AggregateValue extends App { var total = 0 //mutable def sum(input: List[Int]): Int = { input.foldLeft(0)((accumulator, item) => accumulator + item) } println(sum(List(1,2,3)))// 6 } |
Example #3: Conditional Aggregates
Java Way
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | object AggregatingConditionally extends App { def statsByExperience(input: List[Person]): SalaryByExperienceTotals = { val stats = new SalaryByExperienceTotals() for (person <- input) { if (person.experience < 10) { stats.underTen += person } else if (person.experience >= 10 && person.experience <= 20) { stats.tenToTwenty += person } else if (person.experience > 20) { stats.overTwenty += person } } stats } val persons = List(Person(25, 4500000), Person(5, 2500000), Person(20, 9500000)) println(statsByExperience(persons)) } case class Person(experience: Int, salaryInCents: Long) case class SalaryByExperienceTotals( underTen: scala.collection.mutable.ListBuffer[Person] = scala.collection.mutable.ListBuffer[Person](), tenToTwenty: scala.collection.mutable.ListBuffer[Person] = scala.collection.mutable.ListBuffer[Person](), overTwenty: scala.collection.mutable.ListBuffer[Person] = scala.collection.mutable.ListBuffer[Person]() ) { override def toString: String = { underTen + " , " + tenToTwenty + " , " + overTwenty } } |
Output: ListBuffer(Person(5,2500000)) , ListBuffer(Person(20,9500000)) , ListBuffer(Person(25,4500000))
Scala Way in Scala using case statements for the conditions & immutable List
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | object AggregatingConditionally extends App { def statsByExperience(input: List[Person]): SalaryByExperienceTotals = { input.foldLeft(new SalaryByExperienceTotals()){ (stats, person) => person match { case _ if(person.experience < 10) => stats.copy(underTen = person :: stats.underTen) case _ if(person.experience >= 10 && person.experience <= 20) => stats.copy(tenToTwenty = person :: stats.tenToTwenty) case _ => stats.copy(overTwenty = person :: stats.overTwenty) } } } val persons = List(Person(25, 4500000), Person(5, 2500000), Person(20, 9500000)) println(statsByExperience(persons)) } case class Person(experience: Int, salaryInCents: Long) case class SalaryByExperienceTotals( underTen: List[Person] = List(), tenToTwenty: List[Person] = List(), overTwenty: List[Person] = List() ) { override def toString: String = { "underTen=" + underTen + " ,tenToTwenty= " + tenToTwenty + " , overTwenty = " + overTwenty } } |
Output:
1 2 3 | underTen=List(Person(5,2500000)) ,tenToTwenty= List(Person(20,9500000)) , overTwenty = List(Person(25,4500000)) |
Case class implicit copy method
When you create a case class in Scala, a copy method is generated for your case class. What does this copy method do?
Copy method lets you copy an object, where a ‘copy’ is different from a clone as you can change fields as desired during the copying process. The copy method is important in functional programming, where values (val) are immutable.
Scala’s ‘::’ operator, how does it work?
The operator :: is a function on a List class. So, “person :: stats.underTen” means
1 2 3 | stats.underTen.::(person) |
adding a person to a list named “underTen”, which is in the case class “SalaryByExperienceTotals”.
E.g. Foo(10) :: List(Foo(2)) means
1 2 3 | List(Foo(2)).::(Foo(10)) |
E.g. In 1 + 2, “+” is a function on the object Int.