Scala for Java developers

Lesson 4: FP & OOP

Function

1. map

 

2. filter

 

3. fold

 

4. foldLeft

Definition

def doSomething(f: (A) ⇒ B): List[B]
def doSomething(p: (A) ⇒ Boolean): List[A]
def doSomething[A1 >: A](z: A1)(op: (A1, A1) ⇒ A1): A1
def doSomething[B](z: B)(op: (B, A) ⇒ B): B

Quiz recap

Function

1. map

 

2. filter

 

3. fold

 

4. foldLeft

Definition

def doSomething(f: (A) ⇒ B): List[B]
def doSomething(p: (A) ⇒ Boolean): List[A]
def doSomething[A1 >: A](z: A1)(op: (A1, A1) ⇒ A1): A1
def doSomething[B](z: B)(op: (B, A) ⇒ B): B

Quiz recap

More higher order functions

find, reduceLeft, reduceRight

find

  • find: find the first element that satisfying a predicate p.

 

 

 

Example

def find(p: A => Boolean): Option[A]
val numbers = List(1,2,3,4,5)

numbers.find(number => number % 3 == 0)
// res0: Option[Int] = Some(3)

numbers.find(number => number % 6 == 0)
// res1: Option[Int] = None

reduceLeft & reduceRight

  • reduceLeft/ reduceRight: iterates over a data structure of type A and aggregates all elements while applying given function with end result of type B >: A

 

 

 

  • similar to foldLeft and foldRight but without initial/default value 

 

 

* B >: A means that the type parameter B or the abstract type B refer to a supertype of type A

 def reduceLeft[B >: A](op: (B, A) => B): B
 def reduceRight[B >: A](op: (A, B) => B): B
def foldLeft[B](z: B)(op: (B, A) => B): B
def foldRight[B](z: B)(op: (A, B) => B): B

Example reduceLeft & reduceRight

  
val numbers = List(1,2,3,4,5) 

findMin(numbers)
// res1: Int = 1

findMin2(numbers)
// res2: Int = 1
  def findMin(list: List[Int]): Int = {
    list.reduceLeft { (a, b) => if (a <= b) a else b }
  }
  def findMin2(list: List[Int]): Int = {
    list.reduceRight { (a, b) => if (a <= b) a else b }
  }
findMin(List.empty[Int])
java.lang.UnsupportedOperationException: empty.reduceLeft
  at scala.collection.LinearSeqOptimized.reduceLeft(LinearSeqOptimized.scala:135)
  at scala.collection.LinearSeqOptimized.reduceLeft$(LinearSeqOptimized.scala:134)
  at scala.collection.immutable.List.reduceLeft(List.scala:86)
  at .findMin(<console>:12)
  ... 38 elided

OOP

traits, case classes

traits

trait <identifier> [extends <identifier>] [{ fields, methods, and classes }]

trait

  • A trait is an abstract interface
  • Similar to Java 8 interface, it may contain implementation of some methods

 

Example

trait HotelService {
  def getHotelNames(hotels: List[Hotel]): List[String]

  def findHotelById(hotels: List[Hotel], id: Int): Option[Hotel]

  def findHotelsByCity(hotels: List[Hotel], city: String): List[Hotel]

  def findCheapestHotel(hotels: List[Hotel]): Hotel
}
trait <identifier> [extends <identifier>] [{ fields, methods, and classes }]

trait

class HotelServiceImpl extends HotelService {
  
  override def getHotelNames(hotels: List[Hotel]): List[String] = ???

  override def findHotelById(hotels: List[Hotel], id: Int): Option[Hotel] = ???

  override def findHotelsByCity(hotels: List[Hotel], city: String): List[Hotel] = ???

  override def findCheapestHotel(hotels: List[Hotel]): Hotel = ???

}

Using a trait

trait

trait PricingService {
  def convertToExchangeRate(prices: List[Integer], rate: Float): List[Integer]

  def findPricesBelowThreshold(prices: List[Integer], threshold: Integer): List[Integer]

  def findMaxPrice(prices: List[Integer]): Option[Integer] = {
    if (prices.isEmpty)
      None
    else
      Some(prices.max)
  }
}

Example with a implemented method

case classes

case class <identifier> ([var] <identifier>: <type>[, ... ])
                        [extends <identifier>(<input parameters>)]
                        [{ fields and methods }]

case class

  • Kind of POJO object but simpler
  • Good for modelling immutable data or DTO
class Hotel {
    private String name;
    private String city;
    private Integer price;

    Hotel(String name, String city, Integer price) {
        this.name = name;
        this.city = city;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public String getCity() {
        return city;
    }

    public Integer getPrice() {
        return price;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Hotel hotel = (Hotel) o;

        if (name != null ? !name.equals(hotel.name) : hotel.name != null) return false;
        if (city != null ? !city.equals(hotel.city) : hotel.city != null) return false;
        return price != null ? price.equals(hotel.price) : hotel.price == null;

    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (city != null ? city.hashCode() : 0);
        result = 31 * result + (price != null ? price.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "Hotel(" + name + ", " + city + ", " + price + ')';
    }
}
case class Hotel(name: String, city: String, price: Int)

case class

  • A case class is similar to a regular class but with some differences:
    • No need of new keyword to create an instance
    • By default parameters of a case class are public value fields, i.e. val
    • Implements equals, hashCode and a nice toString
    • Has a copy method
case class Hotel(name: String, city: String, price: Int)
case class <identifier> ([var] <identifier>: <type>[, ... ])
                        [extends <identifier>(<input parameters>)]
                        [{ fields and methods }]

case class

case class Hotel(name: String, city: String, price: Int)

// new case class instance

val hiltonHotel = Hotel("Hilton London Canary Wharf", "London", 111)
// Using the copy method

val hiltonHotel2 = hiltonHotel.copy(name = "DoubleTree by Hilton - Chelsea")
// hiltonHotel2: Hotel = Hotel(DoubleTree by Hilton - Chelsea,London,111)
// Accessing parameters

val hilton2Nigths = hiltonHotel.price * 2
// hilton2Nigths: Int = 222
// using default toString

println(hiltonHotel)
// Hotel(Hilton London Canary Wharf,London,111)

Time for exercises!

Give us your feedback :)

https://goo.gl/forms/hXIvwwhslM0yXEC83

Scala for Java developers. Lesson4

By Sonia Fernández Rodríguez

Scala for Java developers. Lesson4

Scala for Java developers. Lesson 4. Higher order functions (find and reduce). Case classes and traits

  • 111