project lambda: evolution of java

51
Project Lambda: Evolution of Java Can Pekdemir

Upload: can-pekdemir

Post on 10-May-2015

415 views

Category:

Technology


3 download

DESCRIPTION

Java 8 features that contain lambda expressions, stream api, optional type, default methods, nashorn javascript engine, metaspace

TRANSCRIPT

Page 1: Project Lambda: Evolution of Java

Project Lambda: Evolution of JavaCan Pekdemir

Page 2: Project Lambda: Evolution of Java

“I would say, for most Java developers, it’s revolutionary. For polyglot programmers, it’s evolutionary”.

Adam Bien - author of Real World Java EE Patterns

Page 3: Project Lambda: Evolution of Java

Agenda• Programming paradigms• Rise of functional programming• Lambda expressions• Functional Interface• Stream API• Other exciting Java 8 features

Page 4: Project Lambda: Evolution of Java

Programming Paradigms• Main programming paradigms• Imperative programming• Functional programming• Logic programming• Object-Oriented Programming?

Page 5: Project Lambda: Evolution of Java

Imperative Programming• Ideas of Von Neumann architecture digital hardware

technology• First do this and next do that• Concentrates on how• Mutable variables• Assignments, control structures if-then-else, loops, etc.

Page 6: Project Lambda: Evolution of Java

Imperative Programming

Total of discounted prices by then which are greater than 20.

BigDecimal totalOfDiscountedPrices = BigDecimal.ZERO;

for(BigDecimal price : prices) { if(price.compareTo(BigDecimal.valueOf(20)) > 0) totalOfDiscountedPrices = totalOfDiscountedPrices.add(price.multiply(BigDecimal.valueOf(0.9)));}

System.out.println("Total of discounted prices: “ + totalOfDiscountedPrices);

Page 7: Project Lambda: Evolution of Java

Functional Programming• Mathematics and the theory of functions• John Backus:”Can programming be liberated from the von

Neumann Style?”• Functions are first class citizens.• Functions can be defined anywhere, inside other functions.• Functions can be passed as argument.

• Typically avoids mutable state.• What we want rather than how to do it.

Page 8: Project Lambda: Evolution of Java

Functional Programming

final BigDecimal totalOfDiscountedPrices = prices.stream().filter(price -> price.compareTo(BigDecimal.valueOf(20)) >

0).map(price -> price.multiply(BigDecimal.valueOf(0.9))) .reduce(BigDecimal.ZERO, BigDecimal::add);

Declarative style: expressions over statements.

Page 9: Project Lambda: Evolution of Java

Execution in the Kingdom of Nouns

button.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent event) {

System.out.println("hi " + name);}});

StateManager.getConsiderationSetter("Noun Oriented Thinking", State.HARMFUL).run();

Steve Yeggehttp://steve-yegge.blogspot.com.tr/2006/03/execution-in-kingdom-of-nouns.html

Page 10: Project Lambda: Evolution of Java

The Difference

“OO makes code understandable by encapsulating moving parts. FP makes code understandable by minimizing moving parts.”

Michael Feathers, author of “Working with legacy code”

Page 11: Project Lambda: Evolution of Java

Functional Programming Rises

• The rise of multicore CPUs and big data.• Need for parallel programming with immutable data.• Declarative programming• Less clutter code

Page 12: Project Lambda: Evolution of Java

Java Evolution• Lack of abstracting over behaviour, not just data• Parallelism should be free, confusing thread api• Need for lazy evaluation over data

Page 13: Project Lambda: Evolution of Java

Behaviour Abstraction• First requirement: filter green apples

public static List<Apple> filterGreenApples(List<Apple> inventory){

List<Apple> result = new ArrayList<>();

for (Apple apple: inventory){

if ("green".equals(apple.getColor())) {

result.add(apple);

}

}

return result;

}

What if they want to according to “red”!

Page 14: Project Lambda: Evolution of Java

Behaviour Abstraction

• Abstracting over color

public static List<Apple> filterApplesByColour(List<Apple> inventory, String color) {

List<Apple> result = new ArrayList<>(); for (Apple apple: inventory){

if ( apple.getColor().equals(color) ) { result.add(apple); }

} return result;}

- What if they want to filter according to weight!

Page 15: Project Lambda: Evolution of Java

Refactoring?public static List<Apple> filterApples(List<Apple> inventory, String color, int weight, boolean flag) {

List<Apple> result = new ArrayList<>(); for (Apple apple: inventory){if ( (flag && apple.getColor().equals(color)) || (!flag &&

apple.getWeight() > weight) ){ result.add(apple); }

} return result;}

List<Apple> greenApples = filterApples(inventory, "green", 0, true);

List<Apple> heavyApples = filterApples(inventory, "", 150, false);

Page 16: Project Lambda: Evolution of Java

Parameterize BehaviourApplePredicate encapsulates a strategy for selecting an apple

public interface ApplePredicate{ boolean test (Apple apple);}

public class AppleWeightPredicate implements ApplePredicate{ public boolean test(Apple apple){ return apple.getWeight() > 150; }}

public class AppleColorPredicate implements ApplePredicate{ public boolean test(Apple apple){

return "green".equals(apple.getColor());} }

Page 17: Project Lambda: Evolution of Java

Filtering by an Abstract Criterion

public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p){

List<Apple> result = new ArrayList<>(); for(Apple apple: inventory){

if(p.test(apple)){ result.add(apple); }

} return result;}

Page 18: Project Lambda: Evolution of Java

Filter with Anonymous ClassList<Apple> redApples = filterApples(inventory,

new ApplePredicate() { public boolean test(Apple apple){

return "red".equals(a.getColor()); }});

- Very bulky and confusing to use.

Page 19: Project Lambda: Evolution of Java

Filter Using Lambda Expression

filterApples(inventory, (Apple apple) -> "red".equals(apple.getColor()));

filterApples(inventory, (Apple apple) -> "green".equals(apple.getColor()));

filterApples(inventory, (Apple apple) -> apple.getWeight() > 150);

Page 20: Project Lambda: Evolution of Java

Refactor Design with Generics

public static <T> List<T> filter(List<T> list, Predicate<T> p){ List<T> result = new ArrayList<>(); for(T e: list){ if(p.test(e)){ result.add(e); }} return result; }

List<Apple> redApples = filter(inventory, (Apple apple) -> "red".equals(apple.getColor()));

List<Integer> evenNumbers = filter(numbers, (Integer i) -> i % 2 == 0);

Page 21: Project Lambda: Evolution of Java

Real World ExamplesAnonymous inner classinventory.sort(new Comparator<Apple>() { public int compare(Apple a1, Apple a2){

return a1.getWeight().compareTo(a2.getWeight()); }});Lambdainventory.sort((Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()));

Anonymous inner classThread t = new Thread(new Runnable() { public void run(){

System.out.println("Hello world"); }});LambdaThread t = new Thread(() -> System.out.println("Hello world"));

Page 22: Project Lambda: Evolution of Java

Lambda Expressions• Anonymous function• Doesn’t have a name• Has a list of parameters, a body, a return type

(List<String> list) -> list.isEmpty() () -> new Apple(10)(Apple a) -> System.out.println(a.getWeight())(String s) -> s.length()(int a, int b) -> a * b(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())

Page 23: Project Lambda: Evolution of Java

Functional Interface• Lambdas are supported by functional interface• An interface with single abstract method

@FunctionalInterfacepublic interface Predicate<T> {

boolean test(T t);}

Page 24: Project Lambda: Evolution of Java

java.util.function• Predefined Functional Interfaces• Function<T,R> : Takes an object of type T and returns R.• Supplier<T> : Just returns an object of type T.• Predicate<T> : returns a boolean value based on type T.• Consumer<T> : performs an action with given type T.

Page 25: Project Lambda: Evolution of Java

Predicate• Defines an abstract method test

Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();

List<String> nonEmpty = filter(listOfStrings, nonEmptyStringPredicate);

Page 26: Project Lambda: Evolution of Java

Consumer• Perform some operation on type T

public interface Consumer<T>{

public void accept(T t);

}

public static <T> void forEach(List<T> list, Consumer<T> c){

for(T i: list){

c.accept(i);

}

}

forEach(Arrays.asList(1,2,3,4,5),(Integer i) -> System.out.println(i));

Page 27: Project Lambda: Evolution of Java

Function• Defines an abstract method named apply, takes an argument T

and returns of type R.

public interface Function<T, R>{

public R apply(T t);

}

public static <T, R> List<R> map(List<T> list, Function<T, R> f) {

List<R> result = new ArrayList<>();

for(T s: list){

result.add(f.apply(s));

}

return result;

}

List<Integer> l = map(Arrays.asList("lambdas","in","action"), (String s) -> s.length());

Page 28: Project Lambda: Evolution of Java

Functional Interface for Primitives

• Performance saving from autoboxing with primitive ones.

public interface IntPredicate{

public boolean test(int t);

}

IntPredicate evenNumbers = (int i) -> i % 2 == 0;

evenNumbers.test(1000);

// true (no boxing)

Predicate<Integer> oddNumbers = (Integer i) -> i % 2 == 1;

oddNumbers.test(1000);

// false (boxing)

Page 29: Project Lambda: Evolution of Java

Type Interference• Deduce appropriate signature and target type

List<Apple> greenApples = filter(inventory, (Apple a) -> "green".equals(a.getColor()));

List<Apple> greenApples = filter(inventory, a -> "green".equals(a.getColor()));

Comparator<Apple> c =(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());

Comparator<Apple> c = (a1, a2) -> a1.getWeight().compareTo(a2.getWeight());

Page 30: Project Lambda: Evolution of Java

Capturing Variables within a Lambda

• The variable should be captured in lambda must be final or “effectively final”.

int portNumber = 1337;//errorportNumber = 31338;Runnable r = () → System.out.println(portNumber);

Page 31: Project Lambda: Evolution of Java

Method References• Another syntax for lambda expressions

Lambda Method reference equivalent

(Apple a)-> a.getWeight() Apple::getWeight

()->Thread.currentThread.dumpStack() Thread.currentThread()::dumpStack

(String s) -> System.out.println(s) System.out::println

Page 32: Project Lambda: Evolution of Java

Stream API• A sequence of elements from a source that supports

aggregate operations.• Stream doesn’t hold all data• Lazily constructed collections• Uses internal iterations• Supports parallelism easily.• java.util.stream

Page 33: Project Lambda: Evolution of Java

Filter• Acceps a predicate to filter

stringCollection .stream() .filter((s) -> s.startsWith("a")) .forEach(System.out::println);

Page 34: Project Lambda: Evolution of Java

Sorted• Sorted in natural order unless you pass a custom Comparator.

stringCollection .stream() .sorted()

.filter((s) -> s.startsWith("a"))

.forEach(System.out::println);

//list interface sort method inventory.sort((a1, a2) -> a1.getWeight().compareTo(a2.getWeight()));//sort by weight

Page 35: Project Lambda: Evolution of Java

Map• Convert each element into another object.• Uses Function interface

stringCollection .stream() .map(String::toUpperCase) .sorted((a, b) -> b.compareTo(a)) .forEach(System.out::println);

Page 36: Project Lambda: Evolution of Java

Reduce• Perform a reduction on the elements of the stream

List<Integer> numbers = Arrays.asList(3,4,5,1,2);

int sum = numbers.stream().reduce(0, (a, b) -> a + b); int sum2 = numbers.stream().reduce(0, Integer::sum); int max = numbers.stream().reduce(0, (a, b) -> Integer.max(a, b));

Page 37: Project Lambda: Evolution of Java

Match• returns a boolean

• boolean anyStartsWithA = stringCollection .stream() .anyMatch((s) -> s.startsWith("a"));

• anyMatch, allMatch, noneMatch

Page 38: Project Lambda: Evolution of Java

Other Useful Methods• distinct > returns a stream of distinct elements• peek > support debugging of elements• limit > returns a stream of elements with maxSize• skip > returns a stream of elements after discarding the first

number of elements of stream.• min, max, count• forEach, collect(toList), findFirst, findAny, of• groupingBy, partitioningBy

Page 39: Project Lambda: Evolution of Java

Lazy Evaluation• Lazy intermediate operations: filter, sorted, map,• Terminal operations: match, count, reduce, collect

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);

List<Integer> twoEvenSquares = numbers.stream()

.filter(n -> n% 2 == 0) .map(n -> n * n) .limit(2) .collect(toList()); System.out.println(twoEvenSquares); // [ 4, 16]

Page 40: Project Lambda: Evolution of Java

Parallelism

Page 41: Project Lambda: Evolution of Java

Parallel Stream• Just use parallelStream method• We should be careful about the collection size for

performance

List<Apple> greenApples = inventory.parallelStream() .filter(a -> "green".equals(a.getColor())) .sorted() .collect(toList());

Page 42: Project Lambda: Evolution of Java

Null Reference Problem• “I call it my billion-dollar mistake. simply because it was so

easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.”

Tony Hoare – developed quick sort, ALGOL

Page 43: Project Lambda: Evolution of Java

Optional TypeOptional<String> reduced = stringCollection

.stream() .sorted() .reduce((s1, s2) -> s1 + "#" + s2);

reduced.ifPresent(System.out::println);

Page 44: Project Lambda: Evolution of Java

Optional TypeOptional<String> optional = Optional.of("test");

optional.isPresent(); // true optional.get(); // "test" optional.orElse("fallback"); // "test” optional.ifPresent((s) -> System.out.println(s.charAt(0))); // "t"

Page 45: Project Lambda: Evolution of Java

Default Methods• Also known as virtual extension methods• Adds methods to interfaces with implementation• Mainly aimed for backward compatibility• Multiple inheritance?, difference from abstract class?

interface Iterable<T> { default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } }}

Page 46: Project Lambda: Evolution of Java

New Date API• Under the package java.time• Looks like Joda-Time library• Immutable classes

LocalTime now1 = LocalTime.now();LocalTime now2 = LocalTime.now();System.out.println(now1.isBefore(now2)); // falseLocalDate today = LocalDate.now(); //immutableLocalDate tomorrow = today.plusDays(1);LocalDate yesterday = tomorrow.minusDays(2);LocalDateTime localDateTime = LocalDateTime.now();

Page 47: Project Lambda: Evolution of Java

Nashorn Javascript Engine• replaces the old Rhino Javascript engine• competes with Google V8(powers Chrome and Node.js)• can be executed command-line with jjs tool or

programmatically• javascript functions can be called from java side

Page 48: Project Lambda: Evolution of Java

Nashorn Javascript Engine

var fun1 = function(name) {

print('Hi there from Javascript, ' + name); return "greetings from javascript"; }; ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");

engine.eval(new FileReader("script.js"));

Invocable invocable = (Invocable) engine;

Object result = invocable.invokeFunction("fun1", ”Liu Kang");

Page 49: Project Lambda: Evolution of Java

Metaspace• A new memory space• Permgen space completely removed• Allocations for the class metadata are now allocated out of

native memory• A new flag is available (MaxMetaspaceSize)

Page 50: Project Lambda: Evolution of Java

Questions?

Page 51: Project Lambda: Evolution of Java

References

• https://github.com/java8/Java8InAction

• http://winterbe.com/posts/2014/03/16/java-8-tutorial/

• http://blog.informatech.cr/2013/04/10/java-optional-objects/

• http://viralpatel.net/blogs/java-8-default-methods-tutorial/

• http://steve-yegge.blogspot.com.tr/2006/03/execution-in-kingdom-of-nouns.html

• http://en.wikipedia.org/wiki/Tony_Hoare

• http://winterbe.com/posts/2014/04/05/java8-nashorn-tutorial/

• http://java.dzone.com/articles/java-8-permgen-metaspace

• Subramaniam, Venkat. (2014) Functional Programming in Java: Harnessing the Power Of Java 8 Lambda Expressions

• Warburton, Richard. (2014) Java 8 Lambdas: Pragmatic Functional Programming

• Urma, Raoul-Gabriel. (2014) Java 8 in Action: Lambdas, Streams and Functional-style Programming