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

Functional Libraries for Java 8 (Jfokus 2017)

Functional Libraries for Java 8 (Jfokus 2017)

Jfokus 2017, Stockholm

363cf27411356afc37199a73bb58bcfe?s=128

Rabea Gransberger

February 08, 2017
Tweet

Transcript

  1. FUNCTIONAL LIBRARIES FOR JAVA 8 Rabea Gransberger @rgransberger

  2. 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.02.2017 2 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  3. Java 8 - Composition BiFunction<Integer, Integer, Integer> add = (x,

    y) -> x + y; BiFunction<…> addAndMultBy5 = add.andThen(x -> x * 5); addAndMultBy5.apply(2, 7); => 45 08.02.2017 3 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  4. Java 8 - Streams intList.stream() .filter(i % 2 == 0)

    .forEach(System.out::println) 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 4 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
  5. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 5
  6. Java 8 Example Map<MonthDay, List<Employee>> 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 6
  7. 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.02.2017

    Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 7
  8. 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.02.2017 8 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  9. 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?! • Need binary compatibility with < Java 8? => Try Retrolambda 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 9
  10. Stream Additions StreamEx jOOλ StreamUtils 08.02.2017 Jfokus / Functional Java

    8 (Rabea Gransberger @rgransberger) 10
  11. StreamEx https://github.com/amaembo/streamex 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger

    @rgransberger) 11
  12. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 12
  13. public static void main(String[] args) { StreamEx<Employee> stream = of(getPersons(toList()));

    println(stream); printEMail(stream); } static void printEMail(Iterable<Employee> iterable) { for (Employee element : iterable) System.out.println(element.getEmail()); } static <T> void println(Stream<T> stream) { stream.forEach(System.out::println); } 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 13
  14. 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<T, Stream<T>>) StreamEx.ofTree(Paths.get("D:/"), listDirs()) => ["D:/", "D:/workspaces", "D:/workspaces/Devoxx"] 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 14
  15. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 15
  16. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 16
  17. Java 8 Example Map<MonthDay, List<Employee>> 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 17
  18. StreamEx - Enhancing Java 8 Streams Map<MonthDay, List<Employee>> 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<MonthDay, List<Employee>> 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 18
  19. 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<List> .equals(from(n.getBirthday()))) .filter(list -> list.size() > 1) .forEach(this::sendMail); 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 19
  20. jOOλ https://github.com/jOOQ/jOOL 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger

    @rgransberger) 20
  21. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 21
  22. 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<Tuple2> • 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 22
  23. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 23
  24. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 24 throws IOException
  25. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 25
  26. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 26 Seq.of(Paths.get("D:","test.csv")) .flatMap(Unchecked.function(Files::lines)) .printOut();
  27. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 27
  28. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 28
  29. Java 8 Example Map<MonthDay, List<Employee>> 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 29
  30. jOOλ - useful extensions to Java 8 lambdas Seq.seq(persons) .filter(p

    -> p.getBirthday().getMonth() == currentMonth) // Seq<Tuple2<MonthDay,List<Employee>>> .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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 30
  31. jOOλ – Window Functions window: Calculations across related elements, without

    grouping, with a single result per input element Seq.of(tuple("2016-09-11", new BigDecimal("-20")), tuple("2016-09-20", new BigDecimal("100")), tuple("2016-09-27", new BigDecimal("-5"))) 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 31 Date Amount Balance 01.09.2016 0 11.09.2016 -20 € -20 20.09.2016 +100 € ? 27.09.2016 -5 € ?
  32. jOOλ – Window Functions Seq.of(tuple("2016-09-11", new BigDecimal("-20")), tuple("2016-09-20", new BigDecimal("100")),

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

    tuple("2016-09-27", new BigDecimal("-5"))) // 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 33
  34. jOOλ – Window Functions Seq.of(tuple("2016-09-11", new BigDecimal("-20")), tuple("2016-09-20", new BigDecimal("100")),

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

    tuple("2016-09-27", new BigDecimal("-5"))) .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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 35 Window
  36. jOOλ – Window Functions Seq.of(tuple("2016-09-11", new BigDecimal("-20")), tuple("2016-09-20", new BigDecimal("100")),

    tuple("2016-09-27", new BigDecimal("-5"))) .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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 36 Window
  37. jOOλ – Window Functions Seq.of(tuple("2016-09-11", new BigDecimal("-20")), tuple("2016-09-20", new BigDecimal("100")),

    tuple("2016-09-27", new BigDecimal("-5"))) .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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 37 Window
  38. jOOλ – Window Functions Seq.of(tuple("2016-09-11", new BigDecimal("-20")), tuple("2016-09-20", new BigDecimal("100")),

    tuple("2016-09-27", new BigDecimal("-5"))) .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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 38
  39. jOOλ – Window Functions Seq.of(tuple("2016-09-11", new BigDecimal("-20")), tuple("2016-09-20", new BigDecimal("100")),

    tuple("2016-09-27", new BigDecimal("-5"))) .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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 39
  40. jOOλ – Window Functions Seq.of(tuple("2016-09-11", new BigDecimal("-20")), tuple("2016-09-20", new BigDecimal("100")),

    tuple("2016-09-27", new BigDecimal("-5"))) .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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 40 Date Amount Balance 01.09.2016 0 11.09.2016 -20 € -20 20.09.2016 +100 € 80 27.09.2016 -5 € 75
  41. Stream Utils (& More Spliterators, CollectorsUtils) https://github.com/JosePaumard/streams-utils 08.02.2017 Jfokus /

    Functional Java 8 (Rabea Gransberger @rgransberger) 41
  42. Stream Utils • Cycling: Takes a stream and repeats it

    forever StreamUtils.cycling(list.stream()).limit(1000) • Grouping: [a, b, c, d],2 => [[a, b], [c, d]] • Repeating: [a, b, c, d],2 => [a, a, b, b, c, c, d, d] • Rolling: [a, b, c, d, e],2 => [[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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 42
  43. CollectorUtils persons.stream() .filter(p -> p.getBirthday().getMonth() == currentMonth) .collect(groupingByThenStream(p -> MonthDay.from(p.getBirthday())))

    .filter(e -> e.getValue().size() > 1) .sorted(Comparator.comparing(Map.Entry::getKey)) .forEach(e -> sendMail(e.getKey(), e.getValue())); 08.02.2017 43 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  44. Stream Utils - Example Election Time, let‘s count the votes

    08.02.2017 44 Jfokus / Functional Java 8 (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 }
  45. Stream Utils - Example List<VotingCard> 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.02.2017 45 Jfokus / Functional Java 8 (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 }
  46. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 46
  47. Logging 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)

    47
  48. Log4j 2 http://logging.apache.org/log4j/2.x 08.02.2017 Jfokus / Functional Java 8 (Rabea

    Gransberger @rgransberger) 48
  49. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 49
  50. Testing JUnit 5 AssertJ 08.02.2017 Jfokus / Functional Java 8

    (Rabea Gransberger @rgransberger) 50
  51. JUnit 5 http://junit.org/junit5 08.02.2017 Jfokus / Functional Java 8 (Rabea

    Gransberger @rgransberger) 51
  52. JUnit 5 – aka JUnit Lambda Milestone 3, GA expected

    end of Q1 2017 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"); 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 52
  53. JUnit 5 • @Test @DisplayName("My 1st JUnit 5 test!") void

    myFirstTest() {} • @Tag("fast") void testIsFastEnoughForHourlyRuns() {} • Parameter Injection: void myFirstTest(TestInfo info) { info.getDisplayName(); } 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 53  not public  Meta-Annotations possible, @MyFastTag
  54. JUnit 5 – Asserts Grouped Asserts: assertAll("names", () -> assertEquals("John",

    firstname), () -> assertEquals("User", lastname)); => MultipleFailuresError: names (2 failures) expected: <John> but was: <Rabea> expected: <User> but was: <Gransberger> 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 54
  55. JUnit 5 – Exceptions Expected Exceptions Throwable e = assertThrows(IOException.class,()

    -> { new URL("http://127.0.0.1") .openStream().read(); }); assertEquals("http://127.0.0.1",e.getMessage()); 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 55
  56. Junit 5 – Checking Timeouts @Test void timeoutExceeded() { assertTimeout(ofMillis(10),

    () -> { TimeUnit.MILLISECONDS.sleep(100); }); } AssertionFailedError: execution exceeded timeout of 10 ms by 90 ms 08.02.2017 56 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  57. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 57
  58. JUnit 5 - Dynamic tests return IntStream.rangeClosed(1, 20) .map(this::fibonacci) 08.02.2017

    Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 58
  59. JUnit 5 - Dynamic tests return IntStream.rangeClosed(1, 20) .map(this::fibonacci) .mapToObj(fibo

    -> dynamicTest( "Fibonacci = " + fibo, // Name () -> testIsOdd(fibo))); // Test Body } 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 59
  60. JUnit 5 - Dynamic tests @TestFactory @DisplayName("all Fibonacci numbers are

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

    odd") Stream<DynamicTest> testFactory() { return IntStream.range(1, 20) .map(this::fibonacci) .mapToObj(fibo -> dynamicTest("Fibonacci = " + fibo, () -> testIsOdd(fibo))); // Test Body } 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 61
  62. AssertJ http://joel-costigliola.github.io/assertj 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger

    @rgransberger) 62
  63. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 63
  64. AssertJ – Fluent Assertions assertThat(myName) .startsWith("Fro") .endsWith("do") .isEqualToIgnoringCase("frodo"); java.lang.AssertionError: Expecting:

    <"Rabea"> to start with: <"Fro"> 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 64
  65. Collections Eclipse Collections 08.02.2017 Jfokus / Functional Java 8 (Rabea

    Gransberger @rgransberger) 65
  66. Eclipse Collections (GS Collections) https://www.eclipse.org/collections 08.02.2017 Jfokus / Functional Java

    8 (Rabea Gransberger @rgransberger) 66
  67. Eclipse Collections - Features you want with the collections you

    need • Mutable, Immutable and primitive Collections • List, Set, Bag, Stack, Map, MultiMap, BiMap • MutableList<String> 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 67
  68. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 68
  69. Eclipse Collections - Primitives MutableIntList numberOfPets = this.people .sortThisByInt(p ->

    p.getNumberOfPets()) .collectInt(p -> p.getNumberOfPets()); 08.02.2017 69 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  70. Functional Programming in Java 8 https://medium.com/@cscalfani/so-you-want-to-be-a-functional-programmer-part-3-1b0fd14eb1a7 08.02.2017 Jfokus / Functional

    Java 8 (Rabea Gransberger @rgransberger) 70
  71. Functional Programming - Recap • Functions and Values treated the

    same, pass functions around • Pure Functions: Same input => same output & no side effects List<String> values = Arrays.asList("A", "B", "C"); calculateResults(values); values => [A, B C] 08.02.2017 71 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  72. Functional Programming - Recap 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! 08.02.2017 72 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  73. Javaslang http://www.javaslang.io 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger

    @rgransberger) 73
  74. Javaslang - functional library for Java 8 • Immutable &

    Persistent Collections: List, Set, Map in variations • Pure Functions • Tuple0 – 8 & Function0 – 8 • Enforces using Javaslang data structures • .toJavaStream() as bridge to Java Streams/Collections • .collector() Methods as bridge from Java Collections • Stream-like methods on all Collections: but different concept 08.02.2017 74 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  75. Javaslang – Currying Function2<Integer, Integer, Integer> sum = (a, b)

    -> a + b; Function1<Integer, Integer> add2 = sum.curried().apply(2); add2.apply(4); => 6 08.02.2017 75 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  76. Javaslang – 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 08.02.2017 76 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  77. Javaslang • Memoization: Function applied once, susequently returns same value

    Function0<Double> memo = of(Math::random) .memoized(); memo.apply() == memo.apply() • Either: Either the left or right value Either<String,Integer> • Validation: Helper for chains of data validation and object creation Validation.combine(validName(name), validAge(age)) .ap(Person::new) 08.02.2017 77 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  78. Java 8 Example Map<MonthDay, List<Employee>> 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 78
  79. Javaslang - Example javaslang.collection.List<Employee> persons = … persons.filter(p -> p.getBirthday().getMonth()

    == currentMonth) .groupBy(e -> MonthDay.from(e.getBirthday())) .filter(v -> v._2.size() > 1) .forEach(JavaslangTest::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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 79
  80. Javaslang - Matching String s = Match(i).of( Case(is(1), "one"), Case(is(2),

    "two"), Case($(), "?") ); 1 => one 2 => two 3 => ? 08.02.2017 80 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  81. Javaslang – 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.02.2017 81 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  82. SQL Jinq 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger

    @rgransberger) 82
  83. Jinq http://www.jinq.org 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger

    @rgransberger) 83
  84. Jinq - LINQ for Java SQL: SELECT C.Name FROM City

    C WHERE C.Population > 25000000 Jinq: List<String> results = streams.streamAll(em, City.class) .where( c -> c.getPopulation() > 25_000_000 ) .select( c -> c.getName() ) .toList(); 08.02.2017 84 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  85. Reactive RxJava Cyclops-React 08.02.2017 Jfokus / Functional Java 8 (Rabea

    Gransberger @rgransberger) 85
  86. Java 8 - CompletableFuture CompletableFuture<List<String>> future = readList(); future .thenApply(list

    -> "List read: " + list) .exceptionally(t -> "Failed: " + t.getMessage()) .thenAccept(System.out::println); 08.02.2017 86 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  87. RxJava 2 https://github.com/ReactiveX/RxJava 08.02.2017 Jfokus / Functional Java 8 (Rabea

    Gransberger @rgransberger) 87
  88. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 88
  89. RxJava - Reactive Extensions for the JVM • Excellent Javadoc

    with Flow Diagrams of operations 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 89
  90. RxJava - Subscribe Observable<String> 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.02.2017 90 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  91. 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.02.2017 91 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  92. 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.02.2017 92 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  93. 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.02.2017 93 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  94. 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.02.2017 94 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  95. Cyclops React http://cyclops-react.io 08.02.2017 Jfokus / Functional Java 8 (Rabea

    Gransberger @rgransberger) 95
  96. cyclops-react Provides reactive extensions or wraps the following libraries •

    jOOλ • RxJava • Javaslang • Pivotal Reactor • Guava • Functional Java 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 96
  97. Microservices Vert.x 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger

    @rgransberger) 97
  98. Vert.x http://vertx.io 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger

    @rgransberger) 98
  99. 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 99
  100. 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.02.2017 100 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  101. 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.02.2017 101 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  102. Summary 08.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)

    102
  103. Libraries • StreamEx • jOOλ • Stream Utils • Log4j

    2 • JUnit 5 • AssertJ • Eclipse Collections • Javaslang • RxJava • cyclops React • Vert.x • Jinq 08.02.2017 103 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)
  104. More Libraries • JDeferred: is a Java Deferred/Promise library similar

    to JQuery's Deferred Object. • 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.02.2017 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger) 104
  105. Questions? Slides & Code: https://rgra.github.io Twitter: @rgransberger Feedback Welcome! 08.02.2017

    105 Jfokus / Functional Java 8 (Rabea Gransberger @rgransberger)