Scala for Java Programmers
-
Upload
eric-pederson -
Category
Technology
-
view
821 -
download
2
description
Transcript of Scala for Java Programmers
![Page 1: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/1.jpg)
Intro to Scala for Java Devs
Sungard– 4/17/2012
![Page 2: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/2.jpg)
Intro
• Eric Pederson – [email protected] – Twitter @ericacm – Sourcedelica.com/blog – Background in Java, Groovy, Javascript, PHP, etc.
• Using Scala for last two years • Two Scala apps developed for NYSE in
Production
![Page 3: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/3.jpg)
Platform at NYSE
• Scala 2.9.1 • JDK 1.6 • Tomcat / JBoss • Maven • Using lots of Java libraries
– Spring, Hibernate, CXF, Mule, ApacheMQ – Bouncycastle, OpenSAML, Velocity, etc, etc.
![Page 4: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/4.jpg)
What is Scala?
• Hybrid Object-Functional language • Statically typed • Developed by Martin Odersky
– Java Generics – Java Compiler (1.3+)
• First release in 2003
![Page 5: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/5.jpg)
What is Scala?
• Designed for general purpose programming
• Performance on par with Java* • Scalable
– Designed to write programs ranging from scripts up to huge systems
– You don’t have to use all of the features to be productive
* There are some gotchas you have to watch out for
![Page 6: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/6.jpg)
Why Should I Use Scala?
• Allows you to write very concise code – Productivity on the level of Groovy / Ruby
• Concurrency-ready • Excellent interoperability with Java code • Lots of other reasons…
![Page 7: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/7.jpg)
Conciseness
• Code size reduced by 2-3x compared to Java
• Less code == easier to read • Less code == fewer bugs
![Page 8: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/8.jpg)
Conciseness
• Type Inference • Expressions, not statements • Higher-ordered functions • Case classes • Pattern matching
![Page 9: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/9.jpg)
Type Inference
• Variables
• Method return types
• Generic type parameters
val subscrip7onEvents = foo()
def listOfPeople = List(“Paul”, “Eric”, “John”, “Mar7n”)
case class MyPair[A, B](x: A, y: B) val p = MyPair(1, “foo”) // p is MyPair[Int, String]
![Page 10: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/10.jpg)
Type inference
• Java
• Scala
HashMap<String, Customer> customers = new HashMap<String, Customer>(); customers.add("id1",
new Customer("Eric", "917-‐444-‐1234"); customers.add("id2",
new Customer("Paul", "718-‐666-‐9876");
val customers = HashMap( "id1"-‐>Customer("Eric", "917-‐434-‐1852"), "id2"-‐>Customer("Paul", "718-‐666-‐9876"))
![Page 11: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/11.jpg)
Expressions, not statements
val server = if (environment == "development”) { val factory = new MBeanServerFactoryBean factory.aberProper7esSet() factory.getObject.asInstanceOf[MbeanServer] } else { val clazz = Class.forName("org.jboss.mx.u7l.MBeanServerLocator") clazz.getMethod("locateJBoss”).invoke(null) } // server is assigned one of the bold values
![Page 12: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/12.jpg)
Expressions, not statements
val n = try { userInput.toInt } catch { case _ => 0 } // n is an Int, 0 if unable to parse userInput
![Page 13: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/13.jpg)
Collections API
• Very comprehensive – For example, over 200 methods on List
• Higher ordered functions – foreach, map, flatMap, exists, forall, find, findAll, filter, groupBy, par77on, etc.
• Concise literals • Immutable and mutable variations
![Page 14: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/14.jpg)
Collection Literals
• val l1 = List(1, 2, 3)
• val m1 = Map(“name” -‐> “Eric”, “city” -‐> “NYC”)
• val s1 = Set(Car(“Ford”), Car(“Isuzu”), Car(“VW”))
![Page 15: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/15.jpg)
Collections API
• Scala
• Java
val groups = subscrip7onEvents.groupBy(e => e.subscrip7on.id)
Map<String, List<SubscripLonEvent>> groups = new HashMap<String, ArrayList<Subscrip7onEvent>(); for (Subscrip7onEvent se : subscrip7onEvents) { ArrayList<Subscrip7onEvent> seList = groups.get(se.subscrip7on.id) if (seList == null) { seList = new ArrayList<Subscrip7onEvent>(); groups.put(se.subscrip7on.id, seList) } seList.add(se); }
![Page 16: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/16.jpg)
Count characters in documents
Try #1 – Java-esque Scala
var total = 0 for (doc <-‐ docs) { total += doc.length }
Try #2 – Use higher order functions var total = 0 docs.foreach(doc => total += doc.length)
![Page 17: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/17.jpg)
Count characters in documents Try #3 – Use fold docs.foldLeb(0)((accum, current) => accum + current.length)
Try #4 – Use type-classes (eg. Numeric) docs.map(_.length).sum
Try #5 – Use the 'view' method to turn multiple passes into one
docs.view.map(_.length).sum
![Page 18: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/18.jpg)
Variables scala> var i = 0 i: Int = 0 scala> i = 2 i: Int = 2 scala> val j = 0 j: Int = 0 scala> j = 3 <console>:8: error: reassignment to val scala> lazy val l = expensiveComputa7on() l: Double = <lazy>
![Page 19: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/19.jpg)
Uniform Access Principle scala> object Ints { | var i = 1 | val j = 2 | def k = i + j | } scala> Ints.i res8: Int = 1 scala> Ints.j res9: Int = 2 scala> Ints.k res10: Int = 3
![Page 20: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/20.jpg)
Uniform Access Principle scala> object M { | private var pm = 0 | def m = pm | def m_=(in: Int) { pm = in } | } scala> import M._ scala> m res5: Int = 0 scala> m = 5 m: Int = 5
![Page 21: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/21.jpg)
Case Classes
• Scala
scala> case class Car(make: String, model: String, mpg: Int) defined class Car scala> val c = Car("Honda", "Civic", 40) c: Car = Car(Honda,Civic,40)
![Page 22: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/22.jpg)
Case Classes
• Java public class Car implements scala.Product, scala.Serializable { final private String make, model; final private int mpg; Car(String make, String model, int mpg) { this.make = make; this.model = model; this.mpg = mpg; } public String getMake() { return make; } public String getModel() { return model; } public int getMpg() { return mpg; } public String toString() { return “Car( “ + make + …. } public boolean equals(Object that) { if (that instanceOf Car) && …… } public int hashCode() { return 19 + …… } public Car copy(String make, String model, int mpg) { ….. } // plus 9 other Scala-‐specific methods }
![Page 23: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/23.jpg)
Case Classes
• Case classes can also have mutable fields and methods
• In Scala you can define multiple classes per source file
case class Car(make: String, model: String, mpg: Int, var odometer) { def driveMiles(miles: Int) { odometer += miles } }
![Page 24: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/24.jpg)
Pattern Matching
• Case Classes
// Class hierarchy: trait Expr case class Num(value : int) extends Expr case class Var(name : String) extends Expr case class Mul(left : Expr, right : Expr) extends Expr // Simplification rule: e match { case Mul(x, Num(1)) ⇒ x case _ ⇒ e }
![Page 25: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/25.jpg)
Pattern Matching
• Match on constants
def describe(x: Any) = x match { case 5 => "five" case true => "truth" case "hello" => "hi!” case Nil => "the empty list" case _ => "something else” }
![Page 26: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/26.jpg)
Pattern Matching
• Typed patterns
def generalSize(x: Any) = x match { case s: String => s.length case m: Map[_, _] => m.size case _ => -‐1 }
![Page 27: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/27.jpg)
No Checked Exceptions
// Look ma, no throws clause! def foo() { throw new java.lang.Excep7on }
![Page 28: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/28.jpg)
Concurrency-readiness
• The future present is many cores • Writing thread-safe code in Java is very
difficult – Mostly due to shared, mutable state
![Page 29: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/29.jpg)
Concurrency-readiness
• Scala – Excellent support for immutability – Actors / Futures – Parallel collections
![Page 30: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/30.jpg)
Immutability
• Case classes • Immutable collections are default
– Copies of collections share data
• val vs. var, val is encouraged • Method parameters are vals
![Page 31: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/31.jpg)
Actors
• Included in standard Scala library • Simplified multithreading and
coordination • Based on message passing
– Each actor has a mailbox queue of messages
• Implementation based on Erlang
![Page 32: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/32.jpg)
Actors
object Coun7ngActor extends Actor { def act() { for (i <-‐ 1 to 10) { println("Number: "+i) Thread.sleep(1000) } } } Coun7ngActor.start()
![Page 33: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/33.jpg)
Actors
import scala.actors.Actor._ val echoActor = actor { while (true) { receive { case msg => println("received: ” + msg) } } } echoActor ! "hello" echoActor ! "world!"
![Page 34: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/34.jpg)
Futures Return a Future immediately, run func in new thread scala> future { Thread.sleep(10000); println("hi"); 10 } res2: scala.actors.Future[Int] = < func7on0> Use the Future apply() method to get the result scala> res2() // blocks wai7ng for sleep() to finish hi res3: Int = 10
![Page 35: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/35.jpg)
Actors / Futures / STM
• Akka provides more robust Actors and Futures
• Also provides – Distributed (Remote) Actors – Software Transactional Memory – Java API
![Page 36: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/36.jpg)
Parallel Collections
• Add .par to collection to get parallel version
• Uses JDK7 fork-join framework • Example:
– Filter is run in parallel, results are collected, then map is run in parallel
myData.par.filter(_.expensiveTest()).map(_.expensiveComputa7on())
![Page 37: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/37.jpg)
Interoperability with Java
• Scala classes are Java classes • You can pass Scala objects to Java
methods and vice-versa • For the most part, seamless interop
– Cannot use Scala-only features from Java
![Page 38: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/38.jpg)
Java Interop Example @En7ty class Subscrip7onEvent { @Id @GeneratedValue var id: Long = _ @ManyToOne(op7onal=false) var subscrip7on: Subscrip7on = _ var address: String = _ @Index(name="Subscrip7onEventStatus") private var status: String = _ def deliveryStatus = DeliveryStatus.withName(status) def deliveryStatus_=(s: DeliveryStatus) { status = s.toString } }
![Page 39: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/39.jpg)
Java Interop Example @Controller @RequestMapping(Array("/report")) class ReportController { class MessageDto(message: Message) { @BeanProperty val id = message.id @BeanProperty val address = message.address // … } @RequestMapping(Array("/messages")) def messages(@RequestParam(value="fromDate”) from: String, map: ExtendedModelMap): String = { //… map.put(“messages”, asJavaCollec7on(messageDtos)) “report/messages” }
![Page 40: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/40.jpg)
JavaConversions
• Add Scala collection API methods to Java collections
import collec7on.JavaConversions._ import collec7on.Iterable import java.u7l.{List=>JList} def goodStudents(students: JList[Student]): Iterable[String] = students.filter(_.score > 5).map(_.name)
![Page 41: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/41.jpg)
Named and Default Params
• Named parameters
• Default parameters
def resize(width: Int, height: Int) = { ... } resize(width = 120, height = 42)
def f(elems: List[Int], x: Int = 0, cond: Boolean = true) f(List(1)) f(Nil, cond = false)
![Page 42: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/42.jpg)
By-name Parameters
• Method parameters can be lazily evaluated
class Logger { def debug(msg: => String) {
if (isDebug) doLog(DEBUG, msg) } } log.debug(“this “ + “ is “ + “expensive”)
![Page 43: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/43.jpg)
Type Conveniences
• Type Aliases type MyMap = mutable.HashMap[String, mutable.HashMap[String, Int]]
• Import Aliases import com.nyx.domain.no7fica7on.{Topic=>DomainTopic}
![Page 44: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/44.jpg)
Mixins
• Multiple implementation inheritance trait UserIden7fierCmd extends ApiKeyCmd { var userId: String = _ def getUser = {…} } trait RoleIdCmd extends ApiKeyCmd { var… def… } object cmd extends UserIden7fierCmd with RoleIdCmd {..}
![Page 45: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/45.jpg)
Duck Typing
type Closeable = { def close(): Unit } def using[T <: Closeable, S] (obj: T)(func: T => S): S = { val result = func (obj) obj.close() result } val fis = new FileInputStream(“data.txt”) using(fis) { f => while (f.read() != -‐1) {} }
![Page 46: Scala for Java Programmers](https://reader033.fdocuments.net/reader033/viewer/2022052410/554f5cadb4c905b9508b54b4/html5/thumbnails/46.jpg)
More Information
• My Scala Links gist – https://gist.github.com/1249298