Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functional Libraries for Java

Functional Libraries for Java

DevoxxUK, London

Rabea Gransberger

May 10, 2018
Tweet

More Decks by Rabea Gransberger

Other Decks in Programming

Transcript

  1. Libraries • jOOλ • VAVr • JUnit 5 • JDeferred

    • RxJava 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)
  2. 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
  3. Back in 2013 @Devoxx UK • First public talk "Effective

    IDE Usage" 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)
  4. 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)
  5. Pure Function List<String> values = Arrays.asList("A", "B", "C"); calculateResults(values); values

    => [A, B, C] 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)
  6. No Pure Function List<String> values = Arrays.asList("A", "B", "C"); calculateResults(values);

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

    static void calculateResults(List<String> values) { if(values.contains("A")){ throw new IllegalStateException("I hate A"); } } => IllegalStateException 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)
  8. 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)
  9. 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)
  10. Java 8 - Composition BiFunction<Integer, Integer, Integer> 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)
  11. Java 8 - Composition / Currying System.out.println(curry(mult(), 5).apply(6)); IntBinaryOperator mult()

    { return (a, b) -> a * b; } IntFunction<Integer> curry(IntBinaryOperator op, int a){ return (b) -> op.applyAsInt(a, b); } 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)
  12. 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
  13. 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)
  14. 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)
  15. 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)
  16. 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)
  17. 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 € ?
  18. 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)
  19. 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)
  20. 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)
  21. 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
  22. 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
  23. 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
  24. 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)
  25. 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)
  26. 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
  27. 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)
  28. VAVr – Currying Function2<Integer, Integer, Integer> sum = (a, b)

    -> a + b; Function1<Integer, Integer> add2 = sum.curried().apply(2); add2.apply(4); => 6 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)
  29. VAVr – Lifting Partial Function: Only defined for non-zero divisors

    Function2<Integer,Integer,Integer> divide = (a, b) -> a / b; divide.apply(5, 0) => throws ArithmeticException Lift to total function: Defined for every input value Function2<Integer, Integer, Option<Integer>> safeDivide = Function2.lift(divide); safeDivide.apply(5, 0) => None 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)
  30. VAVr • Memoization: Function applied once, susequently returns same value

    Function0<Double> memo = of(Math::random) .memoized(); double first = memo.apply(); double second == memo.apply(); first == second 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)
  31. 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)
  32. 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)
  33. Java 8 - CompletableFuture CompletableFuture<List<String>> 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)
  34. 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)
  35. RxJava - Reactive Extensions for the JVM • Excellent Javadoc

    with Flow Diagrams of operations 10.05.2018 DevoxxUK / Functional Java (Rabea Gransberger @rgransberger)
  36. 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)
  37. 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)
  38. 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)