Upload
richard-walker
View
34
Download
0
Embed Size (px)
Citation preview
FUNctional Programming in Java
8An introduction to functional programming, lambdas, and
streams
Richard WalkerSeptember 2016
Outline Java is changing
Paradigm shift
What is functional programming?
Anonymous functions (Lambdas)
Streams
Filter
Map
Reduce
Examples
Java is evolving and so should we
“It is not the strongest of the species that survives, nor the most intelligent that survives. It is the one that is most adaptable to change” – Charles Darwin
Java 8 allows for cleaner and more concise code Takes advantage of multicore architectures without synchronized
Collections.sort(inventory, new Comparator <Apple>() {public int compare (Apple a1, Apple a2) {
return a1.getWeight().compareTo(a2.getWeight());}
});
inventory.sort(comparing(Apple::getWeight)); Java 8
We’re still learning how to code
Procedur
al
Object-
Oriented
Functional
C, Fortran, Perl
Java, C++, Python
Lisp, Scala, Clojure, Java 8*
https://twitter.com/jongold/status/757262853388677120
https://twitter.com/iamdevloper
What is functional programming? Declarative Programming Paradigm
What you want done instead of how it gets done
Accomplish tasks by composing small functions
No side effects No mutation = easier debugging Allows for safe parallelization
Quick Quiz
Imperative Wayint result = 0;
for(int e: numbers) {
if(e % 2 == 0) {
result += e * 2;
}
}
Functional Way Inumbers.stream()
.filter(e -> e % 2 == 0)
.mapToInt(e -> e * 2)
.sum();
Functional Way IInumbers.stream()
.filter(Numbers::evenNumber)
.mapToInt(Numbers::doubleNumber)
.sum();
Lambdas Anonymous functions
like an anonymous inner class Functional Interfaces
An interface with one abstract method (NEW!)* 1st-class citizens in Java 8Format:(parameters) -> (expression)
Examples:(int a, int b) -> a * b(a, b) -> a * b
Functional Interfaces in Java Oracle provided a bunch of them fresh out of the
box!
Predicate<T> : T -> Boolean
Function<T, R> : T -> R
https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html
Lambda Example// Java 7
List<Person> people = loadPeople();
Collections.sort(people, new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.name.compareTo(p2.name);
}
});
Lambda Example// Java 7
List<Person> people = loadPeople();
Collections.sort(people, new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.name.compareTo(p2.name);
}
});
Lambda Example// Java 8
List<Person> people = loadPeople();
Collections.sort(people,
(Person p1, Person p2)
p1.name.compareTo(p2.name);
);
Lambda Example// Java 8
List<Person> people = loadPeople();
Collections.sort(people,
(Person p1, Person p2) -> p1.name.compareTo(p2.name);
);
Lambda Example// Java 8
List<Person> people = loadPeople();
Collections.sort(people,
(Person p1, Person p2) -> p1.name.compareTo(p2.name);
);
Lambda Example// Java 8
List<Person> people = loadPeople();
Collections.sort(people,
(p1, p2) -> p1.name.compareTo(p2.name);
);
Lambda Example// Java 8
List<Person> people = loadPeople();
people.sort((p1, p2) -> p1.name.compareTo(p2.name));
• Less code
• Easier to read
• Less chance for screw ups
We’re using the new sort API added to java.util.List in Java 8 – instead of the old Collections.sort API.
Streams“The gateway drug of Java 8” - Venkat Subramaniam
What are Streams? Allows for Collection manipulation in a
Declarative way Functional
Allows us to abstract away from iteration Less boilerplate code
Allows for composable code Greater Flexibility
Allows for easy (free) parallelization Better Performance
Filtering (Extracts)
// Filtering unique elements
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
.filter(i -> i % 2 == 0)
.distinct()
.forEach(System.out::println);
Mapping (Transforms)
// Map
List<String> words = Arrays.asList("Hello", "World");
List<Integer> wordLengths = words.stream()
.map(String::length)
.collect(toList());
System.out.println(wordLengths);
Reducing (Folds/Massages)
List<Integer> numbers = Arrays.asList(3,4,5,1,2);
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
System.out.println(sum);
int sum2 = numbers.stream()
.reduce(0, Integer::sum);
System.out.println(sum2);
Filtering (Extracts) faster!
// Filtering unique elements
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.parallelStream() .filter(i -> i % 2 == 0)
.distinct()
.forEach(System.out::println);
ExamplesHow can I actually use this at work?
class Person { Gender gender; String name; public Gender getGender() { return gender; } public String getName() { return name; }}
enum Gender { MALE, FEMALE, OTHER }
List<String> names = new ArrayList<String>();
List<Person> people = …
people.stream()
.filter(p -> p.getGender() == Gender.FEMALE)
.map(Person::getName)
.map(String::toUpperCase)
.forEach(name -> names.add(name));
List of uppercase names of all the “FEMALE” people in that list
Get the unique surnames in uppercase of the first 15 book authors that are 50 years old or older.library.stream()
.map(book -> book.getAuthor())
.filter(author -> author.getAge() >= 50)
.map(Author::getSurname)
.map(String::toUpperCase)
.distinct()
.limit(15)
.collect(toList()));
Real-life examplesReducing QA work one line at a time
QA Implementation Pt.1
public static PartnerInfo[] arrayCopy(final PartnerInfo... info) {
if (info == null) {
return null;
}
final PartnerInfo[] result = new PartnerInfo[info.length];
for (int i = 0; i < info.length; i++) {
result[i] = new PartnerInfo(info[i]);
}
return result;
}
286 chars, 9 lines
QA Implementation Pt.2public static PartnerInfo[] arrayCopy(final PartnerInfo... info) {
if (info == null) {
return null;
}
// Create a new copy for each PartnerInfo in the list
return Arrays.stream(info)
.map(PartnerInfo::new)
.toArray(PartnerInfo[]::new);
}
194 chars, 7 lines
Differences
Imperative 9 Lines 286 Chars
Declarative 7 Lines 194 Chars
92 characters less32.17% decrease!
Conclusion
Paradigms are changing, and languages are evolving Java 8 has a host of new features:
Lambdas Stream API
Functional Code has the following benefits: Flexible Less Code*