Slide 1

Slide 1 text

Functional Libraries for Java Rabea Gransberger (MEKO-S GmbH) @rgransberger 8, 9, ….

Slide 2

Slide 2 text

Libraries • jOOλ • VAVR • JUnit 5 • JDeferred • RxJava • Vert.x 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 3

Slide 3 text

Rabea Gransberger • Computer Science Diploma 2008 • Java Developer, Project Lead at MEKOS, Germany • Organization Team JUG Bremen, JCrete 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger) By Karte: NordNordWest, Lizenz: Creative Commons by-sa-3.0 de, CC BY-SA 3.0 de, https://commons.wikimedia.org/w/index.php?curid=35392837

Slide 4

Slide 4 text

Functional Programming in Java https://medium.com/@cscalfani/so-you-want-to-be-a-functional-programmer-part-3-1b0fd14eb1a7 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 5

Slide 5 text

Functional Programming - Recap 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 6

Slide 6 text

Functional Programming - Recap Functions and Values treated the same, pass functions around • Higher-Order Functions: Take function as param or return it • Referential transparency: call can be replaced by value • same input/same output • no side effects (exceptions) • Pure Functions: all functions called are referential transparent • Immutable data structures • Closures/Lambdas • Composition, Lifting, Currying • Filter / Map / Reduce 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 7

Slide 7 text

Pure Function List values = Arrays.asList("A", "B", "C"); calculateResults(values); values => [A, B, C] 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 8

Slide 8 text

No Pure Function List values = Arrays.asList("A", "B", "C"); calculateResults(values); static void calculateResults(List values) { values.removeIf(s -> s.length() < 2); } => [ ] Favor Immutable data structures! 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 9

Slide 9 text

No Pure Function List values = Arrays.asList("A", "B", "C"); calculateResults(values); static void calculateResults(List values) { if(values.contains("A")){ throw new IllegalStateException("I hate A"); } } => IllegalStateException 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 10

Slide 10 text

Java 8 – Functional-"ish" Additions • SAM types enable Lambdas & are backwards compatible • New Functional Interfaces: Function, Predicate, Supplier, Consumer, .. • Default Methods now allow: list.sort( comparing(Person::getName) ) 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 11

Slide 11 text

Java 8: Higher Order Function public static void main(String[] args) { System.out.println(add().applyAsInt(5, 6)); } private static IntBinaryOperator add() { return (a, b) -> a + b; } 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 12

Slide 12 text

Java 8 - Composition BiFunction add = (x, y) -> x + y; BiFunction<…> addAndMultBy5 = add.andThen(x -> x * 5); addAndMultBy5.apply(2, 7); => 45 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 13

Slide 13 text

Java 8 - Composition / Currying System.out.println(curry(mult(), 5).apply(6)); IntBinaryOperator mult() { return (a, b) -> a * b; } IntFunction curry(IntBinaryOperator op, int a){ return (b) -> op.applyAsInt(a, b); } 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 14

Slide 14 text

Java 8 – Streams: Filter / Map / Reduce intList.stream() .filter(i % 2 == 0) .forEach(System.out::println) 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger) Terminal • reduce / collect / toArray • allMatch / anyMatch / noneMatch • count • findAny / findFirst • forEach / forEachOrdered / iterator / spliterator • max / min Intermediate • filter / distinct • map / flatMap • limit / skip • peek • sorted / unordered • dropWhile/takeWhile

Slide 15

Slide 15 text

Functional Programming - Java ? Functions and Values treated the same, pass functions around √ Higher-Order Functions x Referential transparency x Pure Functions √ Closures/Lambdas √ Composition, Lifting, Currying √ Filter / Map / Reduce 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 16

Slide 16 text

Before we start… • Other JVM languages are more functional • Java is conservative • Additional API might be added later • As usual: Test drive a new library before you use it in production Performance?! 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 17

Slide 17 text

Birthday breakfast • Get list of employees • Find all birthdays this month • Group by birthday • Send E-Mail to each group and ask them to organize breakfast together Let’s code this! By Matt @ PEK from Taipei, Taiwan (Buffet brekafast) [CC BY-SA 2.0] via https://commons.wikimedia.org/wiki/File%3ABuffet_brekafast_(5078306699).jpg 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 18

Slide 18 text

Java 8 Example Map> byDate = persons.stream() .filter(p -> p.getBirthday().getMonth() == currentMonth) .collect(groupingBy(e -> MonthDay.from(e.getBirthday()))); byDate.entrySet().stream() .filter(e -> e.getValue().size() > 1) .sorted(comparing(Map.Entry::getKey)) .forEach(e -> sendMail(e.getKey(), e.getValue())); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 19

Slide 19 text

By Anneli Salo (Own work) [CC BY-SA 3.0], https://commons.wikimedia.org/wiki/File%3AFolk_Music_%26_Limbo_Dance_C_IMG_2636.JPG 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 20

Slide 20 text

Java 8 • How's that method called again? • Comparator instead of Function • Functions like zip • How do I get a stream of lines from File? • Lack of Immutable data structures 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 21

Slide 21 text

Stream Additions StreamEx jOOλ StreamUtils 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 22

Slide 22 text

StreamEx https://github.com/amaembo/streamex 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 23

Slide 23 text

StreamEx - Enhancing Java 8 Streams • StreamEx class wraps Stream • StreamEx.of(list.stream()) • StreamEx.of(1,2,3) • Allows parallel execution • Short-Cut Collectors: • stream.joining(",") instead of • stream.collect(joining(",")) • Additional Collectors in MoreCollectors and Joining (for Strings) • Special Streams/Collectors for primitives 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 24

Slide 24 text

public static void main(String[] args) { StreamEx stream = of(getPersons(toList())); println(stream); printEMail(stream); } static void printEMail(Iterable iterable) { for (Employee element : iterable) System.out.println(element.getEmail()); } static void println(Stream stream) { stream.forEach(System.out::println); } 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 25

Slide 25 text

StreamEx – Factory Methods • StreamEx.ofLines(Path) • ofKeys/Values(Map) • cartesianProduct: [[A,B][1,2]] => [[A, 1], [A,2], [B, 1], [B, 2]] • split("Firstname-Name-Title", "-") => ["Firstname", "Name", "Title"] • zip: [[A,B,Rabea][1,2,Gransberger]] => [A1, B2, Rabea Gransberger] • ofTree(T, Function>) StreamEx.ofTree(Paths.get("D:/"), listDirs()) => ["D:/", "D:/workspaces", "D:/workspaces/Devoxx"] 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 26

Slide 26 text

StreamEx – EntryStream for Map.Entry • Factory methods: EntryStream.of(map) • Key/Value pairs: of("Rabea","Gransberger","Devoxx, "MA") => [Rabea ~ Gransberger, Devoxx ~ MA] • Two Lists: [A,B][1,2] => [A ~ 1, B ~ 2] • map/filter/peek/remove separate for Keys/Values of(K,V,K2,V2).filterKeys(k -> k.endsWith("2")) => [K2 ~ V2] 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 27

Slide 27 text

StreamEx – Cherry Picks • prepend/append: of(1,2).prepend(0) => [0,1,2] • foldLeft/foldRight: Aggregate into single result, starting left or right of(1,2,3).foldLeft(0, Integer::sum) => 6 • groupRuns(BiPredicate): groups adjacent elements of(A,B,A,A,B).groupRuns((x,y)->x.equals(y)) => [(A),(B),(A,A),(B)] • distinct(atLeast) distinct values which are contained atLeast times of(A,B,A,A,B,C).distinct(2) => [A,B] 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 28

Slide 28 text

Java 8 Example Map> byDate = persons.stream() .filter(p -> p.getBirthday().getMonth() == currentMonth) .collect(groupingBy(e -> MonthDay.from(e.getBirthday()))); byDate.entrySet().stream() .filter(e -> e.getValue().size() > 1) .sorted(comparing(Map.Entry::getKey)) .forEach(e -> sendMail(e.getKey(), e.getValue())); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 29

Slide 29 text

StreamEx - Enhancing Java 8 Streams Map> byDate = StreamEx.of(persons) .filter(p -> p.getBirthday().getMonth() == currentMonth) .groupingBy(e -> MonthDay.from(e.getBirthday())); EntryStream.of(byDate) .filterValues(l -> l.size() > 1) .sortedBy(Map.Entry::getKey) .forKeyValue(List2Map::sendMail); Map> byDate = persons.stream() .filter(p -> p.getBirthday().getMonth() == currentMonth) .collect(groupingBy(e -> MonthDay.from(e.getBirthday()))); byDate.entrySet().stream() .filter(e -> e.getValue().size() > 1) .sorted(comparing(Map.Entry::getKey)) .forEach(e -> sendMail(e.getKey(), e.getValue())); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 30

Slide 30 text

StreamEx - Enhancing Java 8 Streams StreamEx.of(persons) .filter(p -> p.getBirthday().getMonth() == currentMonth) .sortedBy(p -> MonthDay.from(p.getBirthday())) .groupRuns((p, n) -> from(p.getBirthday()) //StreamEx .equals(from(n.getBirthday()))) .filter(list -> list.size() > 1) .forEach(this::sendMail); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 31

Slide 31 text

jOOλ https://github.com/jOOQ/jOOL 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 32

Slide 32 text

jOOλ - useful extensions to Java 8 lambdas • Seq implements Stream, Iterable • sequential and ordered streams (parallel has no effect) • Similar functionality to StreamEx (no primitives) • SQL Like Collectors (RANK, MODE, BIT_AND) • Function1 - Function16 • Tuple1 - Tuple16 Seq.of(tuple(1, 2, 3, 4)) .mapToLong(t -> t.v1 * t.v2 * t.v3 * t.v4); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 33

Slide 33 text

jOOλ DEMO 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 34

Slide 34 text

jOOλ – Factory methods • Seq.cast(Stream, Class): cast all elements to class • cycle: repeat stream infinitly or certain amount of times • scanLeft/scanRight: fold with intermediate results • grouped: by Function resulting in Seq • range(from,to[,step]): for byte, char, int, long, short, Instant • unfold(seed, Function) • zip/zipAll: with up to 16 Collections/Stream to Tuples/Streams 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 35

Slide 35 text

jOOλ – Helpers for single results • foldLeft/foldRight(stream, seed,BiFunction) producing folded result • groupBy(Function[,Function]): Resulting in a map • splitAt(postion): splitting stream at a position into 2 Streams • toCollection/toList/toMap/toSet • toString(String delimiter): Short for Joining • unzip: unzip one Stream into two with mapping functions 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 36

Slide 36 text

jOOλ - Unchecked Checked Exceptions not allowed in java.util.function Interfaces Seq.of(Paths.get("D:","test.csv")) .flatMap(file -> Files.lines(file)) .printOut(); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger) throws IOException

Slide 37

Slide 37 text

jOOλ - Unchecked Seq.of(Paths.get("D:","test.csv")) .flatMap(file -> { try {return Files.lines(file);} catch (IOException e) { throw new RuntimeException(e);} }) .printOut(); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 38

Slide 38 text

jOOλ - Unchecked Wraps Checked Exceptions into unchecked • Runnable • Comparator • Consumer/BiConsumer • Function/BiFunction • Predicate/BiPredicate • Supplier • BinaryOperator / UnaryOperator • With Variants for primitives ToDoubleBiFunction etc. 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger) Seq.of(Paths.get("D:","test.csv")) .flatMap(Unchecked.function(Files::lines)) .printOut();

Slide 39

Slide 39 text

jOOλ – Cherry Picking • format: Format contents of stream (for debugging) • intersperse: Insert element between existing [a, b, c], 0 => [a,0,b,0,c] • leftOuterJoin: Take all from left, join with each right, by join criteria [a, b, c][1, 2] => [(a,1),(a,2),(b,1),(b,2),(c,null)] • rightOuterJoin: Take all from right, join with each left, by join criteria [a, b][1, 2, 3] => [(a,1),(b,1),(a,2),(b,2),(null,3)] • innerJoin: join until one of the Seq ends, by join criteria [a, b][1, 2, 3] => [(a,1),(b,1),(a,2),(b,2)] 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 40

Slide 40 text

jOOλ – SQL Like Collectors (Agg) With optional Function, Comparator, Predicate • count / sum / avg / median • min / max • allMatch / anyMatch / noneMatch • bitAnd / bitOr • mode / modeAll • rank / denseRank / percentRank / percentile • commonPrefix / commonSuffix of Strings 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 41

Slide 41 text

Java 8 Example Map> byDate = persons.stream() .filter(p -> p.getBirthday().getMonth() == currentMonth) .collect(groupingBy(e -> MonthDay.from(e.getBirthday()))); byDate.entrySet().stream() .filter(e -> e.getValue().size() > 1) .sorted(comparing(Map.Entry::getKey)) .forEach(e -> sendMail(e.getKey(), e.getValue())); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 42

Slide 42 text

jOOλ - useful extensions to Java 8 lambdas Seq.seq(persons) .filter(p -> p.getBirthday().getMonth() == currentMonth) // Seq>> .grouped(e -> MonthDay.from(e.getBirthday()), toList()) .filter(t -> t.v2.size() > 1) .sorted(t -> t.v1) // Function .forEach(t -> sendMail(t.v1, t.v2)); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 43

Slide 43 text

jOOλ – Window Functions window: Calculations across related elements, without grouping, with a single result per input element Seq.of(tuple("2016-09-27", new BigDecimal("-5")), tuple("2016-09-20", new BigDecimal("100")), tuple("2016-09-11", new BigDecimal("-20"))) 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger) Date Amount Balance 01.09.2016 0 11.09.2016 -20 € -20 20.09.2016 +100 € ? 27.09.2016 -5 € ?

Slide 44

Slide 44 text

jOOλ – Window Functions Seq.of(tuple("2016-09-27", new BigDecimal("-5")), tuple("2016-09-20", new BigDecimal("100")), tuple("2016-09-11", new BigDecimal("-20"))) .window(comparing(t -> t.v1), Long.MIN_VALUE, 0) 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 45

Slide 45 text

jOOλ – Window Functions Seq.of(tuple("2016-09-27", new BigDecimal("-5")), tuple("2016-09-20", new BigDecimal("100")), tuple("2016-09-11", new BigDecimal("-20"))) // ordering by date and taking into account // all previous of each date // until the element itself (0) .window(comparing(t -> t.v1), Long.MIN_VALUE, 0) 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 46

Slide 46 text

jOOλ – Window Functions Seq.of(tuple("2016-09-27", new BigDecimal("-5")), tuple("2016-09-20", new BigDecimal("100")), tuple("2016-09-11", new BigDecimal("-20"))) .window(comparing(t -> t.v1), Long.MIN_VALUE, 0) (2016-09-11, -20), (2016-09-20, 100), (2016-09-27, -5) 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 47

Slide 47 text

jOOλ – Window Functions Seq.of(tuple("2016-09-27", new BigDecimal("-5")), tuple("2016-09-20", new BigDecimal("100")), tuple("2016-09-11", new BigDecimal("-20"))) .window(comparing(t -> t.v1), Long.MIN_VALUE, 0) (2016-09-11, -20), (2016-09-20, 100), (2016-09-27, -5) 2016-09-11 -> (2016-09-11, -20) 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger) Window

Slide 48

Slide 48 text

jOOλ – Window Functions Seq.of(tuple("2016-09-27", new BigDecimal("-5")), tuple("2016-09-20", new BigDecimal("100")), tuple("2016-09-11", new BigDecimal("-20"))) .window(comparing(t -> t.v1), Long.MIN_VALUE, 0) (2016-09-11, -20), (2016-09-20, 100), (2016-09-27, -5) 2016-09-11 -> (2016-09-11, -20) 2016-09-20 -> (2016-09-11, -20), (2016-09-20, 100) 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger) Window

Slide 49

Slide 49 text

jOOλ – Window Functions Seq.of(tuple("2016-09-27", new BigDecimal("-5")), tuple("2016-09-20", new BigDecimal("100")), tuple("2016-09-11", new BigDecimal("-20"))) .window(comparing(t -> t.v1), Long.MIN_VALUE, 0) (2016-09-11, -20), (2016-09-20, 100), (2016-09-27, -5) 2016-09-11 -> (2016-09-11, -20) 2016-09-20 -> (2016-09-11, -20), (2016-09-20, 100) 2016-09-27 -> (2016-09-11, -20), (2016-09-20, 100), (2016-09-27, -5) 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger) Window

Slide 50

Slide 50 text

jOOλ – Window Functions Seq.of(tuple("2016-09-27", new BigDecimal("-5")), tuple("2016-09-20", new BigDecimal("100")), tuple("2016-09-11", new BigDecimal("-20"))) .window(comparing(t -> t.v1), Long.MIN_VALUE, 0) .map(w -> w.value() // Tuple2 .concat( // Tuple2 -> Tuple3 // sum over all values in this window w.sum(t -> t.v2).orElse(BigDecimal.ZERO))) 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 51

Slide 51 text

jOOλ – Window Functions Seq.of(tuple("2016-09-27", new BigDecimal("-5")), tuple("2016-09-20", new BigDecimal("100")), tuple("2016-09-11", new BigDecimal("-20"))) .window(comparing(t -> t.v1), Long.MIN_VALUE, 0) .map(w -> w.value().concat( // sum over all values in this window w.sum(t -> t.v2).orElse(BigDecimal.ZERO))) 2016-09-11 -> -20 2016-09-20 -> -20 + 100 = 80 2016-09-27 -> -20 + 100 - 5 = 75 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 52

Slide 52 text

jOOλ – Window Functions Seq.of(tuple("2016-09-27", new BigDecimal("-5")), tuple("2016-09-20", new BigDecimal("100")), tuple("2016-09-11", new BigDecimal("-20"))) .window(comparing(t -> t.v1), Long.MIN_VALUE, 0) .map(w -> w.value().concat( w.sum(t -> t.v2).orElse(BigDecimal.ZERO))) .printOut(); (2016-09-27, -5, 75) (2016-09-20, 100, 80) (2016-09-11, -20, -20) 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger) Date Amount Balance 01.09.2016 0 11.09.2016 -20 € -20 20.09.2016 +100 € 80 27.09.2016 -5 € 75

Slide 53

Slide 53 text

Stream Utils (aka More Spliterators) https://github.com/JosePaumard/streams-utils 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 54

Slide 54 text

Stream Utils • Cycling: Takes a stream and repeats it forever StreamUtils.cycling(list.stream()).limit(1000) • Grouping: [a, b, c, d] => [[a, b], [c, d]] • Repeating: [a, b, c, d] => [a, a, b, b, c, c, d, d] • Rolling: [a, b, c, d, e] => [[a, b], [b, c], [c, d] , [d, e]] • Zipping: The zipping operator takes two streams and a BiFunction [a,b][1,2] => [a1, b2] • Interrupting/Gating: Stops/Starts stream processing by predicate [a,b,c,d] Interrupt c => [a, b] Gate c => [c, d] 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 55

Slide 55 text

Stream Utils - Example Election Time, let‘s count the votes 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger) interface Vote { default int getCandiate1() {return 0;} default int getCandidate2() {return 0;} default int getInvalid() {return 0;} } class VotingCard { //valid //invalid String candidate1Vote; //x //x String candidate2Vote; //null //Hate U }

Slide 56

Slide 56 text

Stream Utils - Example List votes = ….. int invalidVotes = StreamUtils.validate(votes.stream(), Elections::validate, //VotingCard -> boolean Elections::validVote, //VotingCard -> (Valid)Vote Elections::invalidVote)//VotingCard -> (Invalid)Vote .mapToInt(Vote::getInvalid) .sum(); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger) interface Vote { default int getCandiate1() {return 0;} default int getCandidate2() {return 0;} default int getInvalid() {return 0;} } class VotingCard { //valid //invalid String candidate1Vote; //x //x String candidate2Vote; //null //Hate U }

Slide 57

Slide 57 text

Stream Utils • Traversing: Takes a set of streams and builds a stream of substreams stream0 = ["a00", "a01", "a02"] stream1 = ["a10", "a11", "a12"] stream2 = ["a20", "a21", "a22"] [["a00", "a10", "a20"], ["a01", "a11", "a21"], ["a02", "a12", "a22"]] • Weaving: Traversing with flatMapping ["a00", "a10", "a20", "a01", "a11", "a21", "a02", "a12", "a22"] 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 58

Slide 58 text

Logging 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 59

Slide 59 text

Log4j 2 http://logging.apache.org/log4j/2.x 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 60

Slide 60 text

Log4j 2.x Java 8 lambda support for lazy logging //< Java 8 if (logger.isTraceEnabled()) { logger.trace("Long-running: {}", expensiveOperation()); } //>= Java 8 logger.trace("Long-running: {}", () -> expensiveOperation()); logger.info( () -> "Long-running operation:" + expensiveOperation()); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 61

Slide 61 text

Collections Eclipse Collections 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 62

Slide 62 text

Eclipse Collections (GS Collections) https://www.eclipse.org/collections 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 63

Slide 63 text

Eclipse Collections - Features you want with the collections you need • Mutable, Immutable and primitive Collections • List, Set, Bag, Stack, Map, MultiMap, BiMap • MutableList mutable = Lists.mutable.of("A", "B"); • ImutableIntList intList = IntLists.immutable.of(1, 2, 3); • Implements Java Collection interfaces and thus provide Stream • Collections have methods directly without Stream • More Collectors in Class Collectors2 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 64

Slide 64 text

Eclipse Collections - Basics • Different naming: detect vs. findFirst, select vs. filter • Does not return Optional but null if nothing found Person person = people .selectWith(Person::hasPet, PetType.CAT) .detect(p -> p.getFirstName().startsWith("R")); Intermediate operations return new lists 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 65

Slide 65 text

Eclipse Collections - Primitives MutableIntList numberOfPets = this.people .sortThisByInt(p -> p.getNumberOfPets()) .collectInt(p -> p.getNumberOfPets()); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 66

Slide 66 text

VAVR http://www.var.io 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 67

Slide 67 text

VAVR - functional library for Java 8 • Immutable & Persistent Collections: List, Set, Map in variations • Pure Functions • Tuple0 – 8 & Function0 – 8 • Enforces using Vavr data structures • Vavr -> Java: toJavaStream() • Java Stream -> Vavr: With Vavr Collectors • Stream-like methods on all Collections: but different concept 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 68

Slide 68 text

VAVR – Currying Function2 sum = (a, b) -> a + b; Function1 add2 = sum.curried().apply(2); add2.apply(4); => 6 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 69

Slide 69 text

VAVR – Lifting Partial Function: Only defined for non-zero divisors Function2 divide = (a, b) -> a / b; divide.apply(5, 0) => throws ArithmeticException Lift to total function: Defined for every input value Function2> safeDivide = Function2.lift(divide); safeDivide.apply(5, 0) => None 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 70

Slide 70 text

VAVR • Memoization: Function applied once, susequently returns same value Function0 memo = of(Math::random) .memoized(); double first = memo.apply(); double second == memo.apply(); first == second 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 71

Slide 71 text

VAVR • Either: Either the left or right value Either • Validation: Helper for chains of data validation and object creation Validation.combine(validName(name), validAge(age)) .ap(Person::new) 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 72

Slide 72 text

Java 8 Example Map> byDate = persons.stream() .filter(p -> p.getBirthday().getMonth() == currentMonth) .collect(groupingBy(e -> MonthDay.from(e.getBirthday()))); byDate.entrySet().stream() .filter(e -> e.getValue().size() > 1) .sorted(comparing(Map.Entry::getKey)) .forEach(e -> sendMail(e.getKey(), e.getValue())); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 73

Slide 73 text

VAVR - Example io.vavr.collection.List persons = … persons.filter(p -> p.getBirthday().getMonth() == currentMonth) .groupBy(e -> MonthDay.from(e.getBirthday())) .filter(v -> v._2.size() > 1) .forEach(VavrTest::sendMail); persons.stream() .filter(p -> p.getBirthday().getMonth() == currentMonth) .collect(groupingBy(e -> MonthDay.from(e.getBirthday()))); .entrySet().stream() .filter(e -> e.getValue().size() > 1) .sorted(comparing(Map.Entry::getKey)) .forEach(e -> sendMail(e.getKey(), e.getValue())); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 74

Slide 74 text

VAVR DEMO 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 75

Slide 75 text

VAVR - Matching String s = Match(i).of( Case(is(1), "one"), Case(is(2), "two"), Case($(), "?") ); 1 => one 2 => two 3 => ? 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 76

Slide 76 text

VAVR – Matching with side-effects Match(arg).of( Case(isIn("-h", "--help"), o -> run(this::displayHelp)), Case(isIn("-v", "--version"), o -> run(this::displayVersion)), Case($(), o -> run(() -> { throw new IllegalArgumentException(arg); })) ); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 77

Slide 77 text

Testing JUnit 5 AssertJ 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 78

Slide 78 text

JUnit 5 http://junit.org/junit5 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 79

Slide 79 text

JUnit 5 • Beta in Milestone 2, GA expected end of 2016 • @Test @DisplayName("My 1st JUnit 5 test!") void myFirstTest() {} • @Tag("fast") void testIsFastEnoughForHourlyRuns() {} • Parameter Injection: void myFirstTest(TestInfo info) { info.getDisplayName(); } 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)  not public  Meta-Annotations possible, @MyFastTag

Slide 80

Slide 80 text

JUnit 5 – aka JUnit Lambda Lazy message evaluation: org.junit.jupiter.api.Assertions assertEquals(2, 2); assertEquals(4, 4, "optional message as last parameter."); assertTrue(2 == 2, () -> "messages can be lazily evaluated"); assumeTrue("DEV".equals(System.getenv("ENV")), () -> "Aborting test: not on dev workstation"); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 81

Slide 81 text

JUnit 5 – aka JUnit Lambda Grouped Asserts: assertAll("names", () -> assertEquals("John", firstname), () -> assertEquals("User", lastname)); => org.opentest4j.MultipleFailuresError: names (2 failures) expected: but was: expected: but was: 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 82

Slide 82 text

JUnit 5 – aka JUnit Lambda Expected Exceptions Throwable e = expectThrows(IOException.class,() -> { new URL("http://127.0.0.1") .openStream().read(); }); assertEquals("Connection refused: connect",e.getMessage()); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 83

Slide 83 text

JUnit 5 - Dynamic tests Are all fibonacci numbers over 2 odd? @Test void testFibonacci1() { testIsOdd(fibonacci(1)); } @Test void testFibonacci2(){ testIsOdd(fibonacci(2));} @Test void testFibonacci3(){ testIsOdd(fibonacci(3));} …. @Test void testFibonacci20(){testIsOdd(fibonacci(20));} 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 84

Slide 84 text

JUnit 5 Demo 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 85

Slide 85 text

JUnit 5 - Dynamic tests return IntStream.rangeClosed(1, 20) .map(this::fibonacci) 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 86

Slide 86 text

JUnit 5 - Dynamic tests return IntStream.rangeClosed(1, 20) .map(this::fibonacci) .mapToObj(fibo -> dynamicTest( "Fibonacci = " + fibo, // Name () -> testIsOdd(fibo))); // Test Body } 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 87

Slide 87 text

JUnit 5 - Dynamic tests @TestFactory @DisplayName("all Fibonacci numbers are odd") Stream testFactory() { return IntStream.rangeClosed(1, 20) .map(this::fibonacci) .mapToObj(fibo -> dynamicTest( "Fibonacci = " + fibo, // Name () -> testIsOdd(fibo))); // Test Body } 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 88

Slide 88 text

JUnit 5 - Dynamic tests @TestFactory @DisplayName("all Fibonacci numbers are odd") Stream testFactory() { return IntStream.range(1, 20) .map(this::fibonacci) .mapToObj(fibo -> dynamicTest("Fibonacci = " + fibo, () -> testIsOdd(fibo))); // Test Body } 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 89

Slide 89 text

AssertJ http://joel-costigliola.github.io/assertj 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 90

Slide 90 text

AssertJ – Fluent Assertions assertThat(fellowshipOfTheRing) .filteredOn(character -> character.getName().contains("o")) .containsOnly(aragorn, frodo, legolas, boromir) .extracting(character -> character.getRace().getName()) .contains("Hobbit", "Elf", "Man"); assertThat(contentOf(xFile)) .startsWith("The Truth") .contains("Is Out") .endsWith("There"); assertThat(frodo) .isEqualToComparingFieldByField(frodoClone); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 91

Slide 91 text

AssertJ – Fluent Assertions assertThat(myName) .startsWith("Fro") .endsWith("do") .isEqualToIgnoringCase("frodo"); java.lang.AssertionError: Expecting: <"Rabea"> to start with: <"Fro"> 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 92

Slide 92 text

SQL Jinq 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 93

Slide 93 text

Jinq http://www.jinq.org 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 94

Slide 94 text

Jinq - LINQ for Java SQL: SELECT * FROM Customer C WHERE C.Name = 'Alice' Proof of concept: database .customerStream() .where(c -> c.getName().equals("Alice")); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 95

Slide 95 text

Reactive CompletableFuture JDeferred RxJava 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 96

Slide 96 text

Java 8 - CompletableFuture CompletableFuture> future = readList(); future .thenApply(list -> "List read: " + list) .exceptionally(t -> "Failed: " + t.getMessage()) .thenAccept(System.out::println); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 97

Slide 97 text

JDeferred http://jdeferred.org/ 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 98

Slide 98 text

JDeferred Java Deferred/Promise library similar to JQuery's Deferred Object. Deferred<> deferred = new DeferredObject<>(); deferred.promise() .done(result -> println("Completed: " + result)) .fail(rejection -> println("Rejected: " + rejection)) .progress(System.out::println) .always((state, result, rejection) -> println(".")); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 99

Slide 99 text

JDeferred Demo 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 100

Slide 100 text

RxJava 2 https://github.com/ReactiveX/RxJava 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 101

Slide 101 text

RxJava - Reactive Extensions for the JVM • Works on Java 6+ with Functional Interfaces for Java 8 • Observable & Flowable are the base classes Observable.fromIterable(asList("Rabea", "Devoxx")) .subscribe(System.out::println); • Sources: InputStreams, Database, Message Bus etc 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 102

Slide 102 text

RxJava - Reactive Extensions for the JVM • Excellent Javadoc with Flow Diagrams of operations 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 103

Slide 103 text

RxJava - Subscribe Observable observ = just("Rabea", "Devoxx", "RxJava") .filter(s -> s.startsWith("R")); observ .map(s -> s.length()) .subscribe(System.out::println); => 5, 6 observ .subscribe(System.out::println); => Rabea, RxJava 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 104

Slide 104 text

RxJava - Basics • map/flatMap/cast/scan • filter • reduce/count / first/last • forEach • distinct/limit/skip • zip/merge/concat/repeat(cycle) • startWith(prepend) / endWith (append) • toList/toMap/toCollection 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 105

Slide 105 text

RxJava – Time is ticking • interval: Observable which creates numbers in time intervals • onBackpressureDrop: Drop items when backpressure builds up • sample: Sampling items in time intervals • take/takeLast/skip/skipLast:Take/Skip items at start/end time window • timeout: apply timeout for each emitted item • window: Group items in time windows 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 106

Slide 106 text

RxJava – Time is ticking • delaySubscription (delay, TimeUnit) • interval: Observable which creates numbers in time intervals • onBackpressureDrop: Drop items when backpressure builds up • sample: Sampling items in time intervals • take/takeLast/skip/skipLast:Take/Skip items at start/end time window • throttleFirst/Last/withTimeout: Get items in a time window • timeout: apply timeout for each emitted item • window: Group items in time windows 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 107

Slide 107 text

RxJava Demo 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 108

Slide 108 text

RxJava – Errors under control • onErrorResumeNext: Resume with another Observable • retry: Retry to subscribe if error occurs • doOnError: Invoke action on error • …DelayError like concatDelayError, delays exception until terminated 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 109

Slide 109 text

Java 9 Flow API The Flow APIs in JDK 9 correspond to the Reactive Streams Specification, which is a defacto standard • Flow.Publisher: subscribe • Flow.Subscriber: onSubscribe, onNext, onError, onComplete • Flow.Subscription: request, cancel • Flow.Processor extends Flow.Subscriber, Flow.Publisher RxJava, Akka and others will likely imlement Flow in the future 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 110

Slide 110 text

Microservices Vert.x 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 111

Slide 111 text

Vert.x http://vertx.io 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 112

Slide 112 text

Vert.x – reactive applications on the JVM Vert.x is event driven and non blocking Has different components, use only what you need: • Core & Web • Data Access: MongoDB, JDBC, Redis, SQL • Integration: Mail Client, Camel Bridge • Authentication: JWT, Shiro, OAuth2 • Reactive: RxJava, Reactive Streams • Microservices: Circuit Breaker, Kubernetes, Consul • Devops: Dropwizard Metrics, Docker • Clustering: Hazelcast, JGroups, Apache Ignite 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 113

Slide 113 text

Vert.x – Simple HTTP Server Vertx.vertx() .createHttpServer() .requestHandler(req -> req.response() .end("Hello World!")) .listen(8080, handler -> { if (handler.succeeded()) System.out.println("http://localhost:8080/"); else System.err.println("Failed to listen on 8080"); }); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 114

Slide 114 text

Vert.x Demo 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 115

Slide 115 text

Vert.x – Read File vertx .fileSystem() .readFile("d:/test.csv", result -> { if (result.succeeded()) System.out.println(result.result()); else System.err.println(result.cause()); }); 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 116

Slide 116 text

Summary 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 117

Slide 117 text

Libraries • StreamEx • jOOλ • Stream Utils • Log4j 2 • JUnit 5 • AssertJ • JDeferred • Eclipse Collections • VAVR • RxJava • Vert.x • Jinq 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 118

Slide 118 text

More Libraries • Java Functions: @FunctionalInterfaces for every function of 0 to 3 arguments • Paguro: Type-safe versions of Clojure's immutable collections • Cucumber Java 8 Support: Step definitions with Lambdas • Ratpack: is a set of Java libraries for building modern HTTP applications. • Atlassian Fugue: Functional Extensions • Lagom: Build greenfield microservices and decompose your Java EE monolith • Akka Streams • Play Framework: High Velocity Web Framework for Java • jOOQ: DSL for typesafe SQL Queries • Derive4J: annotation processor for deriving algebraic data types 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 119

Slide 119 text

Java 10 (or later) Pattern matching: http://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html String formatted = exprswitch (obj) { case Integer i -> String.format("int %d", i); case Byte b -> String.format("byte %d", b); case Long l -> String.format("long %d", l); case Double d -> String.format(“double %f", d); default -> String.format("String %s", s); }; 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)

Slide 120

Slide 120 text

Q & A Slides & Code: https://rgra.github.io Twitter: @rgransberger Feedback Welcome! 08.11.2017 Øredev / Functional Java (Rabea Gransberger @rgransberger)