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

Functional Libraries for Java

Functional Libraries for Java

DevoxxUK, London

Avatar for Rabea Gransberger

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)