Upload
ganesh-samarthyam
View
2.031
Download
4
Embed Size (px)
Citation preview
Programming paradigms
Langauge Paradigm
Declarative Languages
Imperative Languages
Logic Languages
Functional Languages
Procedural Languages
Object-Oriented Languages
e.g. Prolog e.g. Haskell e.g. C e.g. Java
Perspective - for loops!List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo");for(String string : strings) {
System.out.println(string);}
External Iteration
Perspective - for loops!
List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo");strings.forEach(string -> System.out.println(string));
Internal Iteration
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
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
Lambdas
List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo");Consumer<String> printString = string -> System.out.println(string); strings.forEach(printString);
Lambda functions!
Lambdas
List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo");Consumer<String> printString = string -> System.out.println(string); strings.forEach(printString);
Capture in a variable
Execute later
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
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.”
Languages that support functional programming
C# (3.0)
Python
JavaScriptD
Fortran 95
Visual Basic
PHP Java (8)
C++11
“Success is very largely a matter of adjusting one's self to the ever-varying and changing environments of life”
- Napoleon Hill
Popular Languages
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
Popular Languages
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
Productive programming with lambdasimportjava.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()}
Workshop overview
❖ Assumes that you already know Java
❖ You’ll know how to use Java 8 lambdas and streams after this session
❖ Try out the programs in your machine
Code examples & images from my upcoming book: Oracle Certified Professional Java SE 8 Programmer Exam
1Z0-809 by S G Ganesh, Hari Kiran Kumar and Tushar Sharma, Apress, December 2015
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(); } }
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
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
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
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
}
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));
Method references
Method references - “syntactic sugar” for lambda functions
They “route” function parameters
arg -> System.out.println(arg)
System.out::println
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);
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
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);
“Effectively final” variables
import java.util.Arrays; import java.util.List;
class PigLatin { public static void main(String []args) { String suffix = "ay"; List<String> strings = Arrays.asList("one", "two", "three", "four"); strings.forEach(string -> System.out.println(string + suffix)); } } Accessing “local variable” suffix
here; hence it is considered “effectively final”
“Effectively final” variablesimport java.util.Arrays; import java.util.List;
class PigLatin { public static void main(String []args) { String suffix = "ay"; List<String> strings = Arrays.asList("one", "two", "three", “four");
suffix = "e"; // assign to suffix variable strings.forEach(string -> System.out.println(string + suffix)); } }
PigLatinAssign.java:9: error: local variables referenced from a lambda expression must be final or effectively final strings.forEach(string -> System.out.println(string + suffix)); ^ 1 error
One-liner #1
Files.lines(Paths.get("FileRead.java")).forEach(System.out::println);
This code prints the contents of the file “FileRead.java” in the
current directory
One-liner #2
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
One-liner #3
new Random().ints().limit(5).forEach(System.out::println);
Generates 5 random integers and prints them on the console
One-liner #4
"hello".chars().sorted().forEach(ch -> System.out.printf("%c ", ch));
Extracts characters in the string “hello”, sorts the chars and prints the chars
First stream example
"hello".chars().sorted().forEach(ch -> System.out.printf("%c ", ch));
The chars() method in String results in a Stream; sorted() sorts
the entries in the stream
// prints e h l l o
Stream pipeline
Streamsource
Intermediateopera1ons
Terminalopera1on
stream
stream
Examples:IntStream.range(),Arrays.stream()
Examples:map(),filter(),dis1nct(),sorted()
Examples:sum(),collect(),forEach(),reduce()
Stream pipeline example
Arrays.stream(Object.class.getMethods()) // source .map(method -> method.getName()) // intermediate op .distinct() // intermediate op .forEach(System.out::println); // terminal operation
Stream pipeline example
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);
Stream pipeline illustration
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();
Stream sources
IntStream.range(1, 6)
You can use range or iterate factory methods in the
IntStream interface
IntStream.iterate(1, i -> i + 1).limit(5)
Stream sources
Arrays.stream(new int[] {1, 2, 3, 4, 5}) Arrays.stream(new Integer[] {1, 2, 3, 4, 5})
You can use the stream() method in java.util.Arrays class to create a
stream from a given array
Stream sources
Stream.of(1, 2, 3, 4, 5) Stream.of(new Integer[]{1, 2, 3, 4, 5})
We can also create streams using factories and builders (e..g, of() and build() methods
in the Stream interface)
Stream.builder().add(1).add(2).add(3).add(4).add(5).build()
Stream sources
• The lines() method in java.nio.file.Files class • The splitAsStream() method in java.util.regex.Pattern class • The ints() method in java.util.Random class • The chars() method in java.lang.String class
There are numerous classes/interfaces in the Java library that return a stream
Intermediate operations
Stream<T> filter(Predicate<? super T> check) Removes the elements for which the check predicate returns false.
<R> Stream<R> map(Function<? super T,? extends R> transform)
Applies the transform() function for each of the elements in the stream.
Stream<T> distinct() Removes duplicate elements in the stream; it uses the equals() method to determine if an element is repeated in the stream.
Stream<T> sorted() Stream<T> sorted(Comparator<? super T> compare)
Sorts the elements in its natural order. The overloaded version takes a Comparator – you can pass a lambda function for that.
Stream<T> peek(Consumer<? super T> consume)
Returns the same elements in the stream, but also executes the passed consume lambda expression on the elements.
Stream<T> limit(long size) Removes the elements if there are more elements than the given size in the stream.
Terminal operations
void forEach(Consumer<? super T> action)
Calls the action for every element in the stream.
Object[] toArray() Returns an Object array that has the elements in the stream.
Optional<T> min(Comparator<? super T> compare)
Returns the minimum value in the stream (compares the objects using the given compare function).
Optional<T> max(Comparator<? super T> compare)
Returns the maximum value in the stream (compares the objects using the given compare function).
long count() Returns the number of elements in the stream.
Using “range” instead of “for” loop
IntStream.range(1, 10).map(i -> i * i).forEach(System.out::println);
Using streams instead of imperative for i = 1 to 1, print i * i
Prints: 1 4 9 16 25 36 49 64 81
“Generating” even numbers
IntStream.iterate(0, i -> i + 2).forEach(System.out::println);
The problem is it creates infinite number of even numbers!
“Generating” limited even numbers
IntStream .iterate(0, i -> i + 2) .limit(5) .forEach(System.out::println);
Using the “limit” function to limit the stream to 5 integers
“Generating” limited even numbers
IntStream .iterate(0, i -> i + 1) .filter(i -> (i % 2) == 0) .limit(5) .forEach(System.out::println);
You can also use the “filter” method
“Reduction” using “sum” function
System.out.println(IntStream.rangeClosed(0, 10).sum());
Sum of integers from 1 to 10 using “implicit reduction”
“Reduction” using “sum” function
System.out.println( IntStream .rangeClosed(1, 5) .reduce((x, y) -> (x * y)) .getAsInt());
Factorial of 5 using “explicit reduce”
Using “map” function
List<String> strings = Arrays.asList("eeny", "meeny", "miny", "mo"); strings.stream().map(value -> value.toUpperCase()).forEach(System.out::println);
public static void printUpperCaseString(String string) { System.out.println(string.toUpperCase()); }
strings.forEach(MethodReference::printUpperCaseString);
Using “collect” function
String boxedString = Arrays .asList("eeny", "meeny", "miny", "mo") .stream() .collect(Collectors.joining(“ ,", "[", "]")); System.out.println(boxedString);
Prints: [eeny, meeny, miny, mo]
Using Files.list()
Files.list(Paths.get(".")) .map(path -> path.toAbsolutePath()) .forEach(System.out::println);
Built-in interfacesPredicate<T> Checks a condition and returns a
boolean value as resultIn filter() method in java.util.stream.Stream which is used to remove elements in the stream that don’t match the given condition (i.e., predicate) as Consumer<T> Operation that takes an argument but
returns nothingIn forEach() method in collections and in java.util.stream.Stream; this method is used for traversing all the elements in the collection or Function<T,
R>Functions that take an argument and return a result
In map() method in java.util.stream.Stream to transform or operate on the passed value and return a result.
Supplier<T> Operation that returns a value to the caller (the returned value could be same or different values)
In generate() method in java.util.stream.Stream to create a infinite stream of elements.
Important stream interfaces
<<interface>>java.u0l.stream.BaseStream
<<interface>>java.u0l.stream.IntStream
<<interface>>java.u0l.stream.LongStream
<<interface>>java.u0l.stream.DoubleStream
<<interface>>java.u0l.stream.Stream<T>
map vs. flatMap methods
1 2 3 4 5
1 4 9 16 25
map(i->i*i)
1 3 5
1 3 5 2 4
flatMap(ints->ints.stream())
2 4
sorted()
1 2 3 4 5
1 4 9 16 25
map(i->i*i)
String limerick = "There was a young lady named Bright " + "who traveled much faster than light " + "She set out one day " + "in a relative way " + "and came back the previous night ";
IntSummaryStatistics wordStatistics = Pattern.compile(" ") .splitAsStream(limerick) .mapToInt(word -> word.length()) .summaryStatistics();
System.out.printf(" Number of words = %d \n Sum of the length of the words = %d \n" + " Minimum word size = %d \n Maximum word size %d \n " +
" Average word size = %f \n", wordStatistics.getCount(), wordStatistics.getSum(), wordStatistics.getMin(), wordStatistics.getMax(), wordStatistics.getAverage());
Data calculation methods in stream
Fork-join frameworkforkJoinAlgorithm() { fork (split) the tasks; join the tasks; compose the results; }
doRecursiveTask(input) { if (the task is small enough to be handled by a thread) { compute the small task; if there is a result to return, do so } else { divide (i.e., fork) the task into two parts call compute() on first task, join() on second task, return combined results } }
Stream - for primesimport java.util.stream.LongStream;
class PrimeNumbers { private static boolean isPrime(long val) { for(long i = 2; i <= val/2; i++) { if((val % i) == 0) { return false; } } return true; } public static void main(String []args) { long numOfPrimes = LongStream.rangeClosed(2, 100_000) .filter(PrimeNumbers::isPrime) .count(); System.out.println(numOfPrimes); } }
Stream - for primesimport java.util.stream.LongStream;
class PrimeNumbers { private static boolean isPrime(long val) { for(long i = 2; i <= val/2; i++) { if((val % i) == 0) { return false; } } return true; } public static void main(String []args) { long numOfPrimes = LongStream.rangeClosed(2, 100_000)
.parallel() .filter(PrimeNumbers::isPrime) .count(); System.out.println(numOfPrimes); } }
Be careful with parallel streamsimport 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); } }
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