Skip to content

Scala For Java Developers

Andrew Serff edited this page Nov 23, 2015 · 1 revision

HOME > [NFJS 2015](NFJS 2015) > [Scala For Java Developers](Scala For Java Developers)

Daniel Hinojosa (@dhinojosa)

Intro

###Positives of Scala

  • Type Inferencing
  • It's like Java++
  • Default: things are Immutable
  • Concurrency APIs

###Negatives of Scala

  • They don't really care about backwards compatability
    • their artifact id in maven central have versions in them...
  • Difficult language to learn

Examples/Notes

Scala can run in an intrepreted mode. You don't need a main method when running in intrepreted mode.

Scala, we prefer Immutability, so your primary constructor should take everything. Unlike Java where you create an object and then set a bunch of things.

The filename doesn't have to equal the Class name in scala. You can have multiple classes in the same file

REPL - Read Evaluate Print Loop

just type scala

:reset - clear everything

:paste - so you can paste a bunch of code, then hit control-D

:help

:quit

You also have up arrow and code completion ("Hello". will show you all the methods on String)

Use it with Java

val alist = new java.util.ArrayList[java.lang.Integer])_

You can put object, class or traits in compliable scala files.

Tools

http://scala-ide.org You can use Scala Worksheets which are like iOS Playgrounds (live coding)

http://hub.darcs.net/psnively/spring-scala

##val vs var val makes an immutable reference var make a mutable reference

val c:Int = 4
val d:Short = 50
val e = 70:Short

:load Employee.scala

class Employee(firstName:String, lastName:String)
val e = new Employee("Bob","Jones")

e has no access to firstName/lastName

Add val to the property and it creates a final member variable for it

class Employee(val firstName:String, lastName:String)
val e = new Employee("Bob","Jones")
println("Fristname: " + e.firstName)

If you use var, it will provide you with a mechanism to change that field):

class Employee(val firstName:String, var lastName:String)
val e = new Employee("Bob","Jones")
println("Fristname: " + e.firstName)
println("lastname: " + e.lastName)
e.lastName = "Saggit"

Again, they don't like var

Weirdness with variable names...

scala> val howMuchCanIMake_? = 5000
howMuchCanIMake_?: Int = 5000

scala> val `Hi there` = 10
Hi there: Int = 10

scala> val `true` = false
true: Boolean = false

scala> val `return` = 20
return: Int = 20

scala> val `void` = 200
void: Int = 200

scala> if (`true`) `return` else `void`
res0: Int = 200

Primitaves

All the same primitives are there and they mean the same (byte is 8 bits, etc).

Operator Overloading:

val b = 13 + 20
val c = 13.+(20)

if, else, loops

val result = if (x > 30) 12 else 14

You hardly use while/do while loops because you have to use a var with them

for ( i <- (1 to 10)) println(i))

for comphrensions:

var r = for (i <- (1 to 10)) yield (i + 2)

Strings

String interplation:

var x = "Lionel Ritchie"
var r = s"Hello $x"
var r = s"Hello ${x.size}"

String formatting:

var r = "Hello %s".format(x)

Class Hierarchy

image

scala.Any is the root of Everything. No more java.lang.Object

Null is the subtype of Any Reference

Nothing is the subtype of Any. Nothing is abstract and final. (Ha)

Methods

def foo(x:Int, y:Int):Int = {
   return x + y
}

THe last evaluated statement is always returned. So you don't need the return:

def foo(x:Int, y:Int):Int = {
   x + y
}

You also don't need the curly braces:

def foo(x:Int, y:Int):Int = x + y

You must have the = if you are returning something from your method. This is wrong:

def foo(x:Int, y:Int):Int {
   x + y
}

This will set the return type to Unit which is basically void

val u = () will return a Unit

A Unit is often referred to as a Pure Side Effect

Setters are a Unit (changing state). Printing to the screen, IO, etc could all be considered Pure Side Effects.

Need getter/setter's?

@BeanProperty will make them generate

Overriding

override def toString = s"Employee($firstName, $lastName)"

Instance

x.isInstanceOf([Employee]) or x.asInstanceOf([Employee])

== is back. Same as .equals()

if you want to test object ref equality you use eq

a eq b

toString, equals, hashcode

Just put case in front of your class and you will get a toString, equals, and hashcode implementations.

case class Employee (blah)...

You also don't need the new keyword when you create them...

Apply

A method named apply is like a default method and you can call it without calling it by name:

scala> class Foo(x:Int) {
     |   def bar(y:Int) = x + y
     | }
defined class Foo

scala> var a = new Foo(10)
a: Foo = Foo@10895b16

scala> a.bar(30)
res0: Int = 40

scala> class Foo(x:Int) {
     |   def apply(y:Int) = x + y
     | }
defined class Foo

scala> var a = new Foo(10)
a: Foo = Foo@41b1f51e

scala> a.apply(30)
res2: Int = 40

scala> a(30)
res3: Int = 40

###In fix operator

scala> case class Foo(x:Int) {
     |    def +(y:Int) = new Foo(x + y)
     | }
defined class Foo

scala> val a = Foo(25)
a: Foo = Foo(25)

scala> a.+(40)
res5: Foo = Foo(65)

scala> a + 30
res6: Foo = Foo(55)

scala> Foo(30) + 100
res7: Foo = Foo(130)

###Right associativity: If a method ends in : then it is right associativity.

scala> case class Foo(x:Int) {
     |    def ~:(y:Int) = new Foo(x + y)
     | }
defined class Foo

scala> Foo(10).~:(30)
res8: Foo = Foo(40)

scala> 30 ~: Foo(40)
res9: Foo = Foo(70)

This is how lists are created

scala> 1 :: 2 :: 3 :: 4 :: Nil
res10: List[Int] = List(1, 2, 3, 4)

It takes Nil (which is an empty list) adds 4, adds 3, adds 2, adds 1.

##Options Some or None are subclasses of Option

Same as the Java 8 Optional

You use it with getOrElse

##Object Singleton:

scala> object MySingleton 
defined object MySingleton

scala> var a = MySingleton
a: MySingleton.type = MySingleton$@697d6ded

scala> var b = MySingleton
b: MySingleton.type = MySingleton$@697d6ded

scala> a == b
res11: Boolean = true

scala> a eq b
res12: Boolean = true
scala> object MySingleton {
     |   var x = 10
     |   def foo(y:Int) = {
     |     x = x + y
     |     x
     |   }
     | }
defined object MySingleton

scala> MySingleton.foo(19)
res13: Int = 29

Companion Object

Object with the same name as a the class and inside the same file.

The object can see the private info inside the class and vice verse

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Employee(val firstName:String, var lastName:String, private val ssn:String)
object Employee {
    def identityTheft(e:Employee) = e.ssn
}

// Exiting paste mode, now interpreting.

defined class Employee
defined object Employee

scala> val e1 = new Employee("Clark","Kent","123-456-1234")
e1: Employee = Employee@34045582

scala> e1.ssn
<console>:14: error: value ssn is not a member of Employee
       e1.ssn
          ^
          
scala> Employee.identityTheft(e1)
res17: String = 123-456-1234

Add a factory, but do it awesomly with apply:

case class Employee(val firstName:String, var lastName:String, private val ssn:String)
object Employee {
    def apply(firstName:String, lastName:String) = new Employee(firstName, lastName, "000-000-0000")
    def identityTheft(e:Employee) = e.ssn
}

##Tuples Java 8 doesn't have Tuples

scala> (1, "Wow")
res22: (Int, String) = (1,Wow)

Same as

val t:Tuple2[Int, String] = Tuple2.apply(1, "Wow")

scala> t._1
res23: Int = 1

scala> t._2
res24: String = Wow

scala> t.swap
res25: (String, Int) = (Wow,1)

Ever want to return more than one return value? just return a Tuple.

##Collections

List

scala> List(1,2,3,4)
res20: List[Int] = List(1, 2, 3, 4)

###Map

cala> var m = Map((1,"One"),(2,"Two"))
m: scala.collection.immutable.Map[Int,String] = Map(1 -> One, 2 -> Two)

scala> var m2 = Map(1 -> "one", 2 -> "two")
m2: scala.collection.immutable.Map[Int,String] = Map(1 -> one, 2 -> two)

Getting values

scala> m.get(1)
res26: Option[String] = Some(One)

scala> m.get(5)
res27: Option[String] = None

scala> m(1)
res28: String = One

scala> m(6)
java.util.NoSuchElementException: key not found: 6
  at scala.collection.MapLike$class.default(MapLike.scala:228)
  at scala.collection.AbstractMap.default(Map.scala:59)
  at scala.collection.MapLike$class.apply(MapLike.scala:141)
  at scala.collection.AbstractMap.apply(Map.scala:59)
  ... 33 elided

###Sets Set(1,2,3,4,5)

scala> "Hello, how is it going".apply(4)
res30: Char = o

Functions and Traits

trait is like an Interface

scala> val f:Function1[String, Int] = new Function1[String, Int]() {
     |   def apply(s:String) = s.size
     | }
f: String => Int = <function1>

scala> f.apply("Captain Crunch")
res31: Int = 14

Short Hand:

scala> val f = (s:String) => s.size
f: String => Int = <function1>

scala> f("Captain Crunch")
res32: Int = 14

Using functions with Collections:

scala> List("colorado","new mexico","arizona").map(f)
res33: List[Int] = List(8, 10, 7)

scala> List(1,2,3,4).map(x => x + 10)
res34: List[Int] = List(11, 12, 13, 14)

scala> List(1,2,3,4).map(_ + 10)
res35: List[Int] = List(11, 12, 13, 14)

_ is the same as it in groovy.

foreach

foreach returns a Unit

scala> List(1,2,3,4).foreach(x => println(x))
1
2
3
4

scala> List(1,2,3,4).foreach(println(_))
1
2
3
4

scala> List(1,2,3,4) foreach println
1
2
3
4

###filter

scala> "Hellllooooo Elaine".filter(x => Set('a','e','i','o','u').contains(x))
res40: String = eoooooaie

Convert a method into a function

scala> class Foo(x:Int) {
     |   def bar(y:Int) = x + y
     | }
defined class Foo

scala> new Foo(10)
res41: Foo = Foo@4926f6d6

scala> var z = res41.bar _
z: Int => Int = <function1>
scala> val foo = new Foo(10);
foo: Foo = Foo@69f4fa56

scala> (1 to 10).map(x => foo.bar(x))
res42: scala.collection.immutable.IndexedSeq[Int] = Vector(11, 12, 13, 14, 15, 16, 17, 18, 19, 20)

scala> (1 to 10).map(foo.bar _)
res43: scala.collection.immutable.IndexedSeq[Int] = Vector(11, 12, 13, 14, 15, 16, 17, 18, 19, 20)

scala> (1 to 10).map(foo.bar)
res44: scala.collection.immutable.IndexedSeq[Int] = Vector(11, 12, 13, 14, 15, 16, 17, 18, 19, 20)

scala> (1 to 10) map foo.bar
res45: scala.collection.immutable.IndexedSeq[Int] = Vector(11, 12, 13, 14, 15, 16, 17, 18, 19, 20)

Uber example

We want to take a list of groceries and turn them into a shopping list.

scala> var groceries = List("Eggs", "Milk", "Pepperoni", "Naan", "Broccoli")
groceries: List[String] = List(Eggs, Milk, Pepperoni, Naan, Broccoli)
scala> groceries.zipWithIndex.map(x => x.swap).map(t => (t._1 +1, t._2)).map(t => s"${t._1}. ${t._2}").mkString("\n")
res52: String =
1. Eggs
2. Milk
3. Pepperoni
4. Naan
5. Broccoli

##Parallelization scala> (1 to 10000).par.map{x => println(Thread.currentThread.getName()); x + 3}

Clone this wiki locally