scala vs java 8 in a java 8 world
TRANSCRIPT
Scala in a Java 8 World
Takeaways
• Why Scala? • Scala still relevant in Java 8 world?
What do we need in a language?
Developers should start thinking about tens, hundreds, and thousands of cores now
“ ” - Intel
Parallel processing is hard
Mutable State
public void setX(int x) {this.x = x;
}
setX(0)async { setX(getX()) + 1) }async { setX(getX()) * 2) }
Scala can help
Functional
Object Oriented
JVM Based
All logos owned by respective companies.
Isn’t Java 8 enough?
It’s all about developer
productivity
class Point { private int x; private int y; public Point(int x, int y) { setX(x); setY(y); } public int getX() { return x; } public void setX(int x) { this.x = x;} public int getY() { return y; } public void setY(int y) { this.y = y;} public boolean equals(Object other) { if (other instanceof Point) { Point otherPoint = (Point) other; return otherPoint.getX() == getX() && otherPoint.getY() == getY(); } else { return false; } } public int hashCode() { return (new Integer[] {getX(), getY()}).hashCode(); } }
case class Point(var x: Int, var y: Int)
Traits abstract class Animal { def speak}
trait FourLeggedAnimal { def walk def run}
trait WaggingTail { val tailLength: Int
def startTail { println("tail started") } def stopTail { println("tail stopped") }}
class Dog extends Animal with WaggingTail with FourLeggedAnimal { def speak { println("Dog says 'woof'") } def walk { println("Dog is walking") } def run { println("Dog is running") }}
Immutable Classes public final class Point { private final int x; private final int y;
public Point(int x, int y) { this.x = x; this.y = y; }
public int getX() { return x; } public int getY() { return y; }}
Java
Scala case class Point(x: Int, y: Int)
Immutable Data Structures
Scala List(1, 2, 3)Set(1, 2, 3)Map(("foo", 1), ("bar", 2))
List<Integer> uList = Arrays.asList(1, 2, 3);
Set<Integer> set = new HashSet<>();set.add(1);set.add(2);Set<Integer> uSet = Collections.unmodifiableSet(set);
Map<String, Integer> map = new HashMap<>();map.put("foo", 1);map.put("bar", 2);Map<String, Integer> uMap = Collections.unmodifiableMap(map);
Java
Lambdas
Scala
peoples.filter(person => person.firstName == “Jon”) !!
peoples.stream().filter( person -> ! person.firstName.equals(”Jon”)).collect(Collectors.toList())
Java
peoples.map(person => person.firstName) List(1, 2, 3).reduce(_+_) // 6 List(1, 2, 3).foreach(println)
public class Person {private String lastName;private String firstName;private String middleName;private String salutation;private String suffix;
public Person(String lastName, String firstName, String middleName,String salutation, String suffix) {
this.lastName = lastName;this.firstName = firstName;this.middleName = middleName;this.salutation = salutation;this.suffix = suffix;
}}
public class Person { public static class PersonBuilder {
public PersonBuilder lastName(String newLastName) { this.lastName = newLastName; return this; } public PersonBuilder firstName(String newFirstName) { this.firstName = newFirstName; return this; } public PersonBuilder middleName(String newMiddleName) { this.middleName = newMiddleName; return this; } public PersonBuilder salutation(String newSalutation) { this.salutation = newSalutation; return this; } public PersonBuilder suffix(String newSuffix) { this.suffix = newSuffix; return this; } public Person build() { return new Person(this); }
}}
Named and Default Parameters
case class Person(salutation: String = "Unknown", firstName: String = "Unknown”, middleName: String = "Unknown", lastName: String = "Unknown", suffix: String = "Unknown")
Person("Mr", "John", "M”, "Doe”, ”Sr") Person(salutation = "Mr", firstName = "John", lastName = "Doe") Person(firstName = "John", middleName = "M", lastName = "Doe") Person(firstName = "John") Person(lastName = "Doe") Person(firstName = "John", lastName = "Doe")
Pattern Matching
def parseArgument(arg : String)
Pattern Matching
def parseArgument(arg : String) = arg match { }
Pattern Matching
def parseArgument(arg : String) = arg match { case ("-‐h" | "-‐-‐help”) => displayHelp() }
Pattern Matching
def parseArgument(arg : String) = arg match { case ("-‐h" | "-‐-‐help”) => displayHelp() case bad => badArgument(bad) }
Pattern Matching
def parseArgument(arg : String, value: Any)
Pattern Matching
def parseArgument(arg : String, value: Any) = (arg, value) match { }
Pattern Matching
def parseArgument(arg : String, value: Any) = (arg, value) match { case ("-‐h" | "-‐-‐help", null) => displayHelp() case ("-‐l", lang) => setLanguageTo(lang) case bad => badArgument(bad) }
Pattern Matching
def parseArgument(arg : String, value: Any) = (arg, value) match { case ("-‐h" | "-‐-‐help", null) => displayHelp() case ("-‐l", lang) => setLanguageTo(lang) case ("-‐o" | "-‐-‐optim", n : Int) if ((0 < n) && (n <= 5)) => setOptimizationLevelTo(n) case ("-‐o" | "-‐-‐optim", badLevel) => badOptimizationLevel(badLevel) case bad => badArgument(bad) }
Patterns
// constant patternscase 0 => "zero”case true => "true”case "hello" => "you said 'hello'”case Nil => "an empty List"
// sequence patternscase List(0, _, _) => "a three-element list with 0 as the first element”case List(1, _*) => "a list beginning with 1, having any number of elements”case Vector(1, _*) => "a vector starting with 1, having any number of elements”
// constructor patternscase Person(first, "Alexander") => s"found an Alexander, first name = $first”case Dog("Suka") => "found a dog named Suka”
I call it my billion-dollar mistake. It was the invention of the null reference in 1965.
“ ” - Tony Hoare
Option
def toInt(in: String): Option[Int] = { try { Some(Integer.parseInt(in.trim))
} catch { case ex: NumberFormatException => None }}
toInt(someString) match { case Some(i) => println(i) case None => println("That didn't work.")}
Collections with Option
val bag = List("1", "2", "foo", "3", "bar")
bag.map(toInt) // List[Option[Int]] = List(Some(1), Some(2), None, Some(3), None)
bag.flatMap(toInt) // List(1, 2, 3)
Summary
• Parallel Processing made easier • Developer Productivity • Java interoperable • Still relevant in a Java 8 world