Slide 1

Slide 1 text

#FunctionalJava @rgransberger Functional Libraries for Java Rabea Gransberger @rgransberger https://rgra.github.io

Slide 2

Slide 2 text

Libraries • jOOλ • VAVr • JUnit 5 • JDeferred • RxJava 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 3

Slide 3 text

Rabea Gransberger • Computer Science Diploma 2008 • Java Developer, Project Lead at MEKOS, Germany • Java Champion • Organization Team JUG Bremen, JCrete, JAlba 10.05.2018 DevoxxUK / 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

Back in 2013 @Devoxx UK • First public talk "Effective IDE Usage" 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Functional Programming - Recap 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 7

Slide 7 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 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 8

Slide 8 text

Pure Function List values = Arrays.asList("A", "B", "C"); calculateResults(values); values => [A, B, C] 10.05.2018 DevoxxUK / 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) { values.removeIf(s -> s.length() < 2); } => [ ] Favor Immutable data structures! 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 10

Slide 10 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 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 11

Slide 11 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) ) 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 12

Slide 12 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; } 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 13

Slide 13 text

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

Slide 14

Slide 14 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); } 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 15

Slide 15 text

Java 8 – Streams: Filter / Map / Reduce intList.stream() .filter(i % 2 == 0) .forEach(System.out::println) 10.05.2018 DevoxxUK / 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 16

Slide 16 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 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 17

Slide 17 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?! 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 18

Slide 18 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 10.05.2018 DevoxxUK / 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 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 20

Slide 20 text

jOOλ https://github.com/jOOQ/jOOL 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 21

Slide 21 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); 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 22

Slide 22 text

jOOλ DEMO 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 23

Slide 23 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"))) 10.05.2018 DevoxxUK / 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 24

Slide 24 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) 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 25

Slide 25 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) 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 26

Slide 26 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) 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 27

Slide 27 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) 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger) Window

Slide 28

Slide 28 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) 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger) Window

Slide 29

Slide 29 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) 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger) Window

Slide 30

Slide 30 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))) 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 31

Slide 31 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 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 32

Slide 32 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) 10.05.2018 DevoxxUK / 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 33

Slide 33 text

VAVr http://www.vavr.io/ 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 34

Slide 34 text

VAVr - functional library for Java • 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 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 35

Slide 35 text

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

Slide 36

Slide 36 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 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 37

Slide 37 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 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 38

Slide 38 text

VAVr DEMO 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 39

Slide 39 text

JUnit 5 http://junit.org/junit5 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 40

Slide 40 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()); 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 41

Slide 41 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));} 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 42

Slide 42 text

JUnit 5 Demo 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 43

Slide 43 text

Reactive CompletableFuture JDeferred RxJava 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

JDeferred http://jdeferred.org/ 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 46

Slide 46 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(".")); 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 47

Slide 47 text

RxJava 2 https://github.com/ReactiveX/RxJava 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

RxJava Demo 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 50

Slide 50 text

Pattern Matching Java x int eval(Node n) { switch(n) { case IntNode(int i): return i; case NegNode(Node n): return -eval(n); case AddNode(Node left, Node right): return eval(left) + eval(right); case MulNode(Node left, Node right): return eval(left) * eval(right); default: throw new IllegalStateException(n); }; } 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 51

Slide 51 text

Summary 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

Q & A Slides & Code: https://rgra.github.io Video with Slides: https://www.youtube.com/watch?v=C5_2d2Bfg2Y Twitter: @rgransberger Feedback Welcome! 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)