Moving to functional programming can result in significantly better code and productivity gains. However, it requires a paradigm shift: you need to move away from imperative and object-oriented thinking to start thinking functionally.
13. 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
14. What are lambda functions?
â 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
15. 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.â
17. Productive programming with lambdas
import java.io.*;
class Type {
public static void main(String []files) {
// process each file passed as argument
for(String file : files) {
// try opening the file with FileReader
try (FileReader inputFile = new FileReader(file)) {
int ch = 0;
while( (ch = inputFile.read()) != -1) {
// ch is of type int - convert it back to char
System.out.print( (char)ch );
}
} catch (FileNotFoundException fnfe) {
System.err.printf("Cannot open the given file %s ", file);
}
catch(IOException ioe) {
System.err.printf("Error when processing file %s; skipping it", file);
}
// try-with-resources will automatically release FileReader object
}
}
}
args.each { println new File(it).getText() }
18. Workshop overview
â Assumes that you already
know Java
â Youâll know how to use Java
lambdas and streams after this
session
â Try out the programs in your
machine
21. Java 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
22. `
() -> 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
28. 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
38. 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
43. 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
44. 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()
45. 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
46. 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.
47. 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.
48. 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
52. â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
53. â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
54. âReductionâ using âsumâ function
System.out.println(IntStream.rangeClosed(0, 10).sum());
Sum of integers from 1 to 10 using âimplicit reductionâ
55. âReductionâ using âsumâ function
System.out.println(
IntStream
.rangeClosed(1, 5)
.reduce((x, y) -> (x * y))
.getAsInt());
Factorial of 5 using âexplicit reduceâ
56. 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);
59. Built-in interfaces
Predicate<T> Checks a condition and returns a
boolean value as result
In 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
argument.
Consumer<T> Operation that takes an argument but
returns nothing
In forEach() method in
collections and in
java.util.stream.Stream; this
method is used for traversing all
the elements in the collection or
stream.
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
In generate() method in
java.util.stream.Stream to
65. 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
66. Final (longer) example
import java.util.stream.*;
import java.nio.file.*;
import java.util.*;
import java.nio.charset.Charset;
import java.io.IOException;
class ReadFile {
public static void main(String []args) throws IOException {
List<String> lines = Files.readAllLines(Paths.get("./Ulysses.txt"), Charset.def
Map<Integer, List<String>> wordGroups
= lines.parallelStream()
.map(line -> line.replaceAll("W", " ").split(" "))
.flatMap(Arrays::stream)
.filter(str -> str.length() > 7)
.distinct()
.sorted()
.collect(Collectors.groupingBy(String::length));
wordGroups.forEach( (count, words) -> {
System.out.printf("word(s) of length %d %n", count);
words.forEach(System.out::println); });
}
}
Lists words organised by
their length in the novel
âUlysses.txtâ