Slide 1

Slide 1 text

FUNCTIONAL LIBRARIES FOR JAVA 8 Rabea Gransberger @rgransberger rgra.github.io

Slide 2

Slide 2 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) ) 02.11.2016 2 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

Java 8 - Streams intList.stream() .filter(i % 2 == 0) .forEach(System.out::println) 02.11.2016 DevoxxMA / 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

Slide 5

Slide 5 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 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 5

Slide 6

Slide 6 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())); 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 6

Slide 7

Slide 7 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 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 7

Slide 8

Slide 8 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 02.11.2016 8 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 9

Slide 9 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?! • Need binary compatibility with < Java 8? => Try Retrolambda 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 9

Slide 10

Slide 10 text

Stream Additions StreamEx jOOλ StreamUtils 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 10

Slide 11

Slide 11 text

StreamEx https://github.com/amaembo/streamex 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 11

Slide 12

Slide 12 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 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 12

Slide 13

Slide 13 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); } 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 13

Slide 14

Slide 14 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"] 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 14

Slide 15

Slide 15 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] 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 15

Slide 16

Slide 16 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] 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 16

Slide 17

Slide 17 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())); 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 17

Slide 18

Slide 18 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())); 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 18

Slide 19

Slide 19 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); 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 19

Slide 20

Slide 20 text

jOOλ https://github.com/jOOQ/jOOL 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 20

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); 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 21

Slide 22

Slide 22 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 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 22

Slide 23

Slide 23 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 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 23

Slide 24

Slide 24 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(); 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 24 throws IOException

Slide 25

Slide 25 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(); 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 25

Slide 26

Slide 26 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. 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 26 Seq.of(Paths.get("D:","test.csv")) .flatMap(Unchecked.function(Files::lines)) .printOut();

Slide 27

Slide 27 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)] 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 27

Slide 28

Slide 28 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 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 28

Slide 29

Slide 29 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())); 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 29

Slide 30

Slide 30 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)); 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 30

Slide 31

Slide 31 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"))) 02.11.2016 DevoxxMA / 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 € ?

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) 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 32

Slide 33

Slide 33 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) 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 33

Slide 34

Slide 34 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) 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 34

Slide 35

Slide 35 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) 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 35 Window

Slide 36

Slide 36 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) 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 36 Window

Slide 37

Slide 37 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) 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 37 Window

Slide 38

Slide 38 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))) 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 38

Slide 39

Slide 39 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 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 39

Slide 40

Slide 40 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) 02.11.2016 DevoxxMA / 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

Slide 41

Slide 41 text

Stream Utils (aka More Spliterators) https://github.com/JosePaumard/streams-utils 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 41

Slide 42

Slide 42 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] 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 42

Slide 43

Slide 43 text

Stream Utils - Example Election Time, let‘s count the votes 02.11.2016 43 DevoxxMA / 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 }

Slide 44

Slide 44 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(); 02.11.2016 44 DevoxxMA / 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 }

Slide 45

Slide 45 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"] 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 45

Slide 46

Slide 46 text

Logging 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 46

Slide 47

Slide 47 text

Log4j 2 http://logging.apache.org/log4j/2.x 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 47

Slide 48

Slide 48 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()); 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 48

Slide 49

Slide 49 text

Testing JUnit 5 AssertJ 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 49

Slide 50

Slide 50 text

JUnit 5 http://junit.org/junit5 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 50

Slide 51

Slide 51 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(); } 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 51  not public  Meta-Annotations possible, @MyFastTag

Slide 52

Slide 52 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"); 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 52

Slide 53

Slide 53 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: 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 53

Slide 54

Slide 54 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()); 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 54

Slide 55

Slide 55 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));} 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 55

Slide 56

Slide 56 text

JUnit 5 - Dynamic tests return IntStream.rangeClosed(1, 20) .map(this::fibonacci) 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 56

Slide 57

Slide 57 text

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

Slide 58

Slide 58 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 } 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 58

Slide 59

Slide 59 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 } 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 59

Slide 60

Slide 60 text

AssertJ http://joel-costigliola.github.io/assertj 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 60

Slide 61

Slide 61 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); 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 61

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

Collections Eclipse Collections 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 63

Slide 64

Slide 64 text

Eclipse Collections (GS Collections) https://www.eclipse.org/collections 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 64

Slide 65

Slide 65 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 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 65

Slide 66

Slide 66 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 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 66

Slide 67

Slide 67 text

Eclipse Collections - Primitives MutableIntList numberOfPets = this.people .sortThisByInt(p -> p.getNumberOfPets()) .collectInt(p -> p.getNumberOfPets()); 02.11.2016 67 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

Functional Programming - Recap • Functions and Values treated the same, pass functions around • Pure Functions: Same input => same output & no side effects List values = Arrays.asList("A", "B", "C"); calculateResults(values); values => [A, B C] 02.11.2016 69 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 70

Slide 70 text

Functional Programming - Recap List values = Arrays.asList("A", "B", "C"); calculateResults(values); static void calculateResults(List values) { values.removeIf(s -> s.length() < 2); } => [ ] Favor Immutable data structures! 02.11.2016 70 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 71

Slide 71 text

Javaslang http://www.javaslang.io 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 71

Slide 72

Slide 72 text

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 02.11.2016 72 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 73

Slide 73 text

Javaslang – Currying Function2 sum = (a, b) -> a + b; Function1 add2 = sum.curried().apply(2); add2.apply(4); => 6 02.11.2016 73 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 74

Slide 74 text

Javaslang – 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 02.11.2016 74 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 75

Slide 75 text

Javaslang • Memoization: Function applied once, susequently returns same value Function0 memo = of(Math::random) .memoized(); memo.apply() == memo.apply() • 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) 02.11.2016 75 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 76

Slide 76 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())); 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 76

Slide 77

Slide 77 text

Javaslang - Example javaslang.collection.List 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())); 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 77

Slide 78

Slide 78 text

Javaslang - Matching String s = Match(i).of( Case(is(1), "one"), Case(is(2), "two"), Case($(), "?") ); 1 => one 2 => two 3 => ? 02.11.2016 78 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 79

Slide 79 text

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); })) ); 02.11.2016 79 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 80

Slide 80 text

SQL Jinq 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 80

Slide 81

Slide 81 text

Jinq http://www.jinq.org 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 81

Slide 82

Slide 82 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")); 02.11.2016 82 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 83

Slide 83 text

Reactive RxJava Cyclops-React 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 83

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

RxJava 2 https://github.com/ReactiveX/RxJava 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 85

Slide 86

Slide 86 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 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 86

Slide 87

Slide 87 text

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

Slide 88

Slide 88 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 02.11.2016 88 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 89

Slide 89 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 02.11.2016 89 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 90

Slide 90 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 02.11.2016 90 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 91

Slide 91 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 02.11.2016 91 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 92

Slide 92 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 02.11.2016 92 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 93

Slide 93 text

Cyclops React http://cyclops-react.io 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 93

Slide 94

Slide 94 text

cyclops-react Provides reactive extensions or wraps the following libraries • jOOλ • RxJava • Javaslang • Pivotal Reactor • Guava • Functional Java 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 94

Slide 95

Slide 95 text

Microservices Vert.x 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 95

Slide 96

Slide 96 text

Vert.x http://vertx.io 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 96

Slide 97

Slide 97 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 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 97

Slide 98

Slide 98 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"); }); 02.11.2016 98 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 99

Slide 99 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()); }); 02.11.2016 99 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 100

Slide 100 text

Summary 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 100

Slide 101

Slide 101 text

Libraries • StreamEx • jOOλ • Stream Utils • Log4j 2 • JUnit 5 • AssertJ • Eclipse Collections • Javaslang • RxJava • cyclops React • Vert.x • Jinq 02.11.2016 101 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)

Slide 102

Slide 102 text

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 02.11.2016 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger) 102

Slide 103

Slide 103 text

Slides & Code: https://rgra.github.io Twitter: @rgransberger Feedback Welcome! 02.11.2016 103 DevoxxMA / Functional Java 8 (Rabea Gransberger @rgransberger)