Functional Programming in Java 8 - Exploiting Lambdas

70
Functional Programming in Java 8 Lambda Functions GANESH & HARI CODEOPS TECHNOLOGIES [email protected] [email protected]

Transcript of Functional Programming in Java 8 - Exploiting Lambdas

Page 1: Functional Programming in Java 8 - Exploiting Lambdas

Functional Programming in Java 8 Lambda Functions

GANESH & HARI CODEOPS TECHNOLOGIES

[email protected]@codeops.tech

Page 2: Functional Programming in Java 8 - Exploiting Lambdas
Page 3: Functional Programming in Java 8 - Exploiting Lambdas

Adapt: Learn functional programming

Page 4: Functional Programming in Java 8 - Exploiting Lambdas

Java meets functional programming (with lambdas)

Page 5: Functional Programming in Java 8 - Exploiting Lambdas

Java is not your grandma’s language anymore!

Page 6: Functional Programming in Java 8 - Exploiting Lambdas

Greek characters are scary!

Page 7: Functional Programming in Java 8 - Exploiting Lambdas

He he, but lambdas are fun, not scary

Page 8: Functional Programming in Java 8 - Exploiting Lambdas

List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo");Consumer<String> printString = string -> System.out.println(string); strings.forEach(printString);

Lambda functions!

Page 9: Functional Programming in Java 8 - Exploiting Lambdas

But what are lambdas?

Page 10: Functional Programming in Java 8 - Exploiting Lambdas

Lambdas is just a fancy name for functions

without a name!

Page 11: Functional Programming in Java 8 - Exploiting Lambdas

What are lambda functions?

❖ (Java 8) One way to think about lambdas is “anonymous function” or “unnamed function” - they are functions without a name and are not associated with any class

❖ They don’t change external state

Page 12: Functional Programming in Java 8 - Exploiting Lambdas

What is functional programming?

❖ Functional languages view programs as an entity—called a function—that accepts inputs and produces output

❖ Functions are connected together by their outputs to other functions’ inputs

❖ Underlying approach: “Evaluate an expression. Then use the results for something else.”

Page 13: Functional Programming in Java 8 - Exploiting Lambdas

Perspective - for loops!List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo");for(String string : strings) {

System.out.println(string);}

External Iteration

Page 14: Functional Programming in Java 8 - Exploiting Lambdas

Perspective - for loops!

List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo");strings.forEach(string -> System.out.println(string));

Internal Iteration

Page 15: Functional Programming in Java 8 - Exploiting Lambdas

Perspective - for loops!

List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo");strings.forEach(string -> System.out.println(string));

Internal Iteration

List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo");for(String string : strings) {

System.out.println(string);}

External Iteration

Page 16: Functional Programming in Java 8 - Exploiting Lambdas

Perspective - for loops!

List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo");strings.forEach(string -> System.out.println(string));

Internal Iteration

List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo");for(String string : strings) {

System.out.println(string);}

External Iteration

Procedural thinking

Functional thinking

Page 17: Functional Programming in Java 8 - Exploiting Lambdas

You can use lambdas for some amazing stuff

Page 18: Functional Programming in Java 8 - Exploiting Lambdas

sediment

pre-carbon

ultra-filter

post-carbon

Filtered water

E.g., you can compose lambda functions as in pipes-and-filters

Page 19: Functional Programming in Java 8 - Exploiting Lambdas

$ cat limerick.txt There was a young lady of Niger Who smiled as she rode on a tiger. They returned from the ride With the lady inside And a smile on the face of the tiger.

Page 20: Functional Programming in Java 8 - Exploiting Lambdas

$ cat limerick.txt | tr -cs "[:alpha:]" "\n" | awk '{print length(), $0}' | sort | uniq

1 a 2 as 2 of 2 on 3 And 3 Who 3 she 3 the 3 was 4 They 4 With 4 face 4 from 4 lady 4 ride 4 rode 5 Niger 5 There 5 smile 5 tiger 5 young 6 inside 6 smiled 8 returned

Page 21: Functional Programming in Java 8 - Exploiting Lambdas

List<String> lines = Files.readAllLines(Paths.get("./limerick.txt"), Charset.defaultCharset());

Map<Integer, List<String>> wordGroups = lines.stream() .map(line -> line.replaceAll("\\W", "\n").split("\n")) .flatMap(Arrays::stream) .sorted() .distinct() .collect(Collectors.groupingBy(String::length));

wordGroups.forEach( (count, words) -> { words.forEach(word -> System.out.printf("%d %s %n", count, word)); });

1 a 2 as 2 of 2 on 3 And 3 Who 3 she 3 the 3 was 4 They 4 With 4 face 4 from 4 lady 4 ride 4 rode 5 Niger 5 There 5 smile 5 tiger 5 young 6 inside 6 smiled 8 returned

Page 22: Functional Programming in Java 8 - Exploiting Lambdas

Lambdas & streams help in productive programming!

Page 23: Functional Programming in Java 8 - Exploiting Lambdas

public static void main(String []file) throws Exception { // process each file passed as argument

// try opening the file with FileReader try (FileReader inputFile = new FileReader(file[0])) { int ch = 0; while( (ch = inputFile.read()) != -1) { // ch is of type int - convert it back to char System.out.print( (char)ch ); } } // try-with-resources will automatically release FileReader object }

public static void main(String []file) throws Exception { Files.lines(Paths.get(file[0])).forEach(System.out::println); }

Existing APIs are enriched with lambdas and streams support

Page 24: Functional Programming in Java 8 - Exploiting Lambdas

Java 8 is the new Groovy ;-)importjava.io.*;

classType{ publicsta7cvoidmain(String[]files){ //processeachfilepassedasargument for(Stringfile:files){ //tryopeningthefilewithFileReader try(FileReaderinputFile=newFileReader(file)){ intch=0; while((ch=inputFile.read())!=-1){ //chisoftypeint-convertitbacktochar System.out.print((char)ch); } }catch(FileNotFoundExcep7onfnfe){ System.err.prinR("Cannotopenthegivenfile%s",file); } catch(IOExcep7onioe){ System.err.prinR("Errorwhenprocessingfile%s;skippingit",file); } //try-with-resourceswillautoma7callyreleaseFileReaderobject } }}

args.each{printlnnewFile(it).getText()}

Page 25: Functional Programming in Java 8 - Exploiting Lambdas

Lambdas in Java 8

Page 26: Functional Programming in Java 8 - Exploiting Lambdas

Java 8 lambdas - “Hello world!”

interface LambdaFunction { void call(); }

class FirstLambda { public static void main(String []args) { LambdaFunction lambdaFunction = () -> System.out.println("Hello world"); lambdaFunction.call(); } }

Page 27: Functional Programming in Java 8 - Exploiting Lambdas

Java 8 lambdas - “Hello world!”

interface LambdaFunction { void call(); }

class FirstLambda { public static void main(String []args) { LambdaFunction lambdaFunction = () -> System.out.println("Hello world"); lambdaFunction.call(); } }

Functional interface - provides signature for lambda functions

Lambda function/expression

Call to the lambda

Prints “Hello world” on the console when executed

Page 28: Functional Programming in Java 8 - Exploiting Lambdas

Parts of a lambda expression

() -> System.out.println("Hello world");

No parameters, i.e., ()

Arrow operator that separates parameters and the body The lambda body

Return type “void” inferred from the body

Page 29: Functional Programming in Java 8 - Exploiting Lambdas

Functional interfaces

@FunctionalInterface interface LambdaFunction { void call(); }

Functional interface

Abstract method providing the signature of the lambda function

Annotation to explicitly state that it is a functional interface

Page 30: Functional Programming in Java 8 - Exploiting Lambdas

Using built-in functional interfaces// within Iterable interface default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t);

} }

// in java.util.function package @FunctionalInterface public interface Consumer<T> {

void accept(T t); // the default andThen method elided

}

Page 31: Functional Programming in Java 8 - Exploiting Lambdas

Using built-in functional interfaces

List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo"); Consumer<String> printString = string -> System.out.println(string); strings.forEach(printString);

List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo"); strings.forEach(string -> System.out.println(string));

Page 32: Functional Programming in Java 8 - Exploiting Lambdas

Method references

Method references - “syntactic sugar” for lambda functions

They “route” function parameters

arg -> System.out.println(arg)

System.out::println

Page 33: Functional Programming in Java 8 - Exploiting Lambdas

Method references

List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo"); Consumer<String> printString = System.out::println; strings.forEach(printString);

Method reference

List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo"); Consumer<String> printString = string -> System.out.println(string); strings.forEach(printString);

Page 34: Functional Programming in Java 8 - Exploiting Lambdas

Method references

Cannot use method references when lambda functions do more than“routing” function parameters

strings.forEach(string -> System.out.println(string.toUpperCase()));

More processing here than just “routing” parameters

Page 35: Functional Programming in Java 8 - Exploiting Lambdas

Method references List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo"); Consumer<String> printString = System.out::println; strings.forEach(printString);

public static void printUpperCaseString(String string) { System.out.println(string.toUpperCase()); }

strings.forEach(MethodReference::printUpperCaseString);

Page 36: Functional Programming in Java 8 - Exploiting Lambdas

Java 8 streams (and parallel streams):Excellent example of applying functional

programming in practice

Page 37: Functional Programming in Java 8 - Exploiting Lambdas

But what are streams?

Page 38: Functional Programming in Java 8 - Exploiting Lambdas

Arrays.stream(Object.class.getMethods()) .map(method -> method.getName()) .distinct() .forEach(System.out::println);

wait equals toString hashCode getClass notify notifyAll

Page 39: Functional Programming in Java 8 - Exploiting Lambdas

Method[] objectMethods = Object.class.getMethods(); Stream<Method> objectMethodStream = Arrays.stream(objectMethods); Stream<String> objectMethodNames

= objectMethodStream.map(method -> method.getName()); Stream<String> uniqueObjectMethodNames = objectMethodNames.distinct(); uniqueObjectMethodNames.forEach(System.out::println);

Arrays.stream(Object.class.getMethods()) .map(method -> method.getName()) .distinct() .forEach(System.out::println);

Breaking up into separate (looong) statements for our understanding

Page 40: Functional Programming in Java 8 - Exploiting Lambdas

stream pipelineStreamsource

Intermediateopera1ons

Terminalopera1on

stream

stream

Examples:IntStream.range(),Arrays.stream()

Examples:map(),filter(),dis1nct(),sorted()

Examples:sum(),collect(),forEach(),reduce()

Page 41: Functional Programming in Java 8 - Exploiting Lambdas

DoubleStream.of(1.0,4.0,9.0) map(Math::sqrt) .peek(System.out::

println)

StreamSource(withelements1.0,4.0,and9.0)

IntermediateOpera=on1(mapsto

elementvalues1.0,2.0,and3.0)

IntermediateOpera=on2

(prints1.0,2.0,and3.0)

.sum();

TerminalOpera=on(returnsthesum6.0)

DoubleStream.of(1.0, 4.0, 9.0) .map(Math::sqrt) .peek(System.out::println) .sum();

Page 42: Functional Programming in Java 8 - Exploiting Lambdas

IntStream.range(1, 6)

You can use range or iterate factory methods in the

IntStream interface

IntStream.iterate(1, i -> i + 1).limit(5)

Page 43: Functional Programming in Java 8 - Exploiting Lambdas

1 2 3 4 5

1 4 9 16 25

map(i->i*i)

IntStream.range(1, 5).map(i -> i * i).forEach(System.out::println);

Using streams instead of imperative for i = 1 to 5, print i * i

Page 44: Functional Programming in Java 8 - Exploiting Lambdas

Stream.of (1, 2, 3, 4, 5) .map(i -> i * i) .peek(i -> System.out.printf("%d ", i)) .count();

prints: 1 4 9 16 25

Page 45: Functional Programming in Java 8 - Exploiting Lambdas

stream can be infinite

IntStream.iterate(0, i -> i + 2).forEach(System.out::println);

This code creates infinite stream of even numbers!

Page 46: Functional Programming in Java 8 - Exploiting Lambdas

IntStream .iterate(0, i -> i + 2) .limit(5) .forEach(System.out::println);

Using the “limit” function to limit the stream to 5 integers

Page 47: Functional Programming in Java 8 - Exploiting Lambdas

IntStream chars = "bookkeep".chars(); System.out.println(chars.count()); chars.distinct().sorted().forEach(ch -> System.out.printf("%c ", ch));

Cannot “reuse” a stream; this code throws IllegalStateException

Page 48: Functional Programming in Java 8 - Exploiting Lambdas

Files.lines(Paths.get("FileRead.java")).forEach(System.out::println);

This code prints the contents of the file “FileRead.java” in the

current directory

Page 49: Functional Programming in Java 8 - Exploiting Lambdas

Pattern.compile(" ").splitAsStream("java 8 streams").forEach(System.out::println);

This code splits the input string “java 8 streams” based on whitespace and hence

prints the strings “java”, “8”, and “streams” on the console

Page 50: Functional Programming in Java 8 - Exploiting Lambdas

new Random().ints().limit(5).forEach(System.out::println);

Generates 5 random integers and prints them on the console

Page 51: Functional Programming in Java 8 - Exploiting Lambdas

"hello".chars().sorted().forEach(ch -> System.out.printf("%c ", ch));

Extracts characters in the string “hello”, sorts the chars and prints the chars

Page 52: Functional Programming in Java 8 - Exploiting Lambdas

Parallel Streams

Page 53: Functional Programming in Java 8 - Exploiting Lambdas

race conditions

Page 54: Functional Programming in Java 8 - Exploiting Lambdas
Page 55: Functional Programming in Java 8 - Exploiting Lambdas

deadlocks

Page 56: Functional Programming in Java 8 - Exploiting Lambdas
Page 57: Functional Programming in Java 8 - Exploiting Lambdas

I really really hate concurrency problems

Page 58: Functional Programming in Java 8 - Exploiting Lambdas

Parallel code

Serial code

Page 59: Functional Programming in Java 8 - Exploiting Lambdas

long numOfPrimes = LongStream.rangeClosed(2, 100_000) .filter(PrimeNumbers::isPrime) .count();

System.out.println(numOfPrimes);

Prints 9592

2.510 seconds

Page 60: Functional Programming in Java 8 - Exploiting Lambdas

Parallel code

Serial code

Let’s flip the switch by calling parallel() function

Page 61: Functional Programming in Java 8 - Exploiting Lambdas

long numOfPrimes = LongStream.rangeClosed(2, 100_000) .parallel() .filter(PrimeNumbers::isPrime) .count();

System.out.println(numOfPrimes);

Prints 9592

1.235 seconds

Page 62: Functional Programming in Java 8 - Exploiting Lambdas

Wow! That’s an awesome flip switch!

Page 63: Functional Programming in Java 8 - Exploiting Lambdas

Internally, parallel streams make use of fork-join framework

Page 64: Functional Programming in Java 8 - Exploiting Lambdas
Page 65: Functional Programming in Java 8 - Exploiting Lambdas

import java.util.Arrays;

class StringConcatenator { public static String result = ""; public static void concatStr(String str) { result = result + " " + str; } }

class StringSplitAndConcatenate { public static void main(String []args) { String words[] = "the quick brown fox jumps over the lazy dog".split(" "); Arrays.stream(words).forEach(StringConcatenator::concatStr); System.out.println(StringConcatenator.result); } }

Gives wrong results with with parallel() call

Page 66: Functional Programming in Java 8 - Exploiting Lambdas
Page 67: Functional Programming in Java 8 - Exploiting Lambdas

Adapt: Learn functional programming

Page 68: Functional Programming in Java 8 - Exploiting Lambdas

Upcoming bootcamps/workshops

Modern Software Architecture - July 2 Modern Programming with Java 8 - July 16 Software Refactoring in Practice - July 23

Page 69: Functional Programming in Java 8 - Exploiting Lambdas

Image credits❖ http://mayhemandmuse.com/wp-content/uploads/2013/04/This-optical-illusion-drawing-by-WE-

Hill-shows-both-his-wife-and-his-mother-in-law.jpg

❖ http://www.webtrafficroi.com/wp-content/uploads/2012/10/mahatma-gandhi-apple-think-different.jpg

❖ http://rexx-language-association-forum.44760.x6.nabble.com/file/n2236/Ruby-lambda-function.jpg

❖ http://www.ibm.com/developerworks/library/j-jn16/figure1.png

❖ http://www.ibm.com/developerworks/library/j-jn16/figure2.png

❖ http://img.viralpatel.net/2014/01/java-lambda-expression.png

❖ http://www.codercaste.com/wp-content/uploads/2011/01/animals.png

❖ http://blog.takipi.com/wp-content/uploads/2014/03/blog_lambada_2.png

❖ http://quotespictures.com/wp-content/uploads/2014/01/it-is-not-the-strongest-of-the-species-that-survive-nor-the-most-intelligent-but-the-one-most-responsive-to-change-charles-darwin.jpg

❖ http://7-themes.com/data_images/out/27/6859733-surfing-wallpaper.jpg