Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Xlab #1: Advantages of functional programming in Java 8

333 views

Published on

Presentation from xlab workshop about functional programming components introduced to the Java 8. How to operate the streams and lambdas in theory and practice.

Published in: Software
  • Be the first to comment

Xlab #1: Advantages of functional programming in Java 8

  1. 1. www.xsolve.plAgile Software House Advantages of functional programming in Java 8
  2. 2. www.xsolve.plAgile Software House
  3. 3. www.xsolve.plAgile Software House ● 10:00 - 10:25 Welcome! ● 10:30 - 10:40 Functional Programming ● 10:40 - 11:55 Lambdas ● 12:10 - 13:25 Streams ● 13:55 - 15:00 File IO Agenda
  4. 4. Functional Programming www.xsolve.plAgile Software House ● Concise ● Little “Boilerplate”
  5. 5. Functional Programming in JVM www.xsolve.plAgile Software House ● Groovy: Closures ● Java 6: ● Java8 - Lambdas!
  6. 6. www.xsolve.plAgile Software House Lambdas
  7. 7. // Java 7 button.addActionListener( new ActionListener () { @Override public void actionPerformed(ActionEvent e){ doSomethingWith(e) ; } }); Motivation www.xsolve.plAgile Software House // Java 8 button.addActionListener( e -> doSomethingWith(e)) ; vs
  8. 8. // Java 7 Collections. sort(list, new Comparator<Integer>() { @Overide public int compare(final Integer o1, final Integer o2) { return o2.compareTo(o1) ; } }); Motivation www.xsolve.plAgile Software House // Java 8 Collections. sort( list, (o1, o2) -> o2.compareTo(o1)) ; vs
  9. 9. Lambda syntax www.xsolve.plAgile Software House new Comparator<String>() { @Override public int compare(final String s1, final String s2) { return s1.length() - s2.length(); } } (s1, s2) -> { return s1.length() - s2.length(); } (s1, s2) -> s1.length() - s2.length() (final String s1, final String s2) -> { return s1.length() - s2.length(); } (final String s1, final String s2) -> { return s1.length() - s2.length(); } (final String s1, final String s2) -> { return s1.length() - s2.length(); } new Comparator<String>() { @Override public int compare(final String s1, final String s2) { return s1.length() - s2.length(); } } (s1, s2) -> { return s1.length() - s2.length(); }
  10. 10. Sorting Strings by Length www.xsolve.plAgile Software House // Java 7 example Collections .sort(list, new Comparator<String>() { @Override public int compare(final String s1, final String s2) { return s1.length() - s2.length() ; } } ); // Java 8 alternative Collections .sort(list, (s1, s2) -> s1.length() - s2.length()) ;
  11. 11. Lambda syntax (one argument) www.xsolve.plAgile Software House (s) -> s.toUpperCase() () -> doSomething() s -> s.toUpperCase()
  12. 12. Method references www.xsolve.plAgile Software House (args) -> ClassName.staticMethodName( args) ClassName::staticMethodName // Examples Math::cos Arrays::sort String::valueOf String::length Integer::compareTo
  13. 13. Method references www.xsolve.plAgile Software House Method Ref Type Example Equivalent Lambda SomeClass::staticMethod Math::cos x -> Math.cos(x) someObject::instanceMethod someString::toUpperCase () -> someString.toUpperCase() SomeClass::instanceMethod String::toUpperCase s -> s.toUpperCase() SomeClass::new Employee::new () -> new Employee()
  14. 14. Lambdas with big body www.xsolve.plAgile Software House addActionListener(e -> { prepareFuel(); /* … */ launch(e); }); addActionListener(this::fireNuclearRocket); void fireNuclearRocket(ActionEvent e) { prepareFuel(); /* … */ launch(e); }
  15. 15. Functional interface www.xsolve.plAgile Software House @FunctionalInterface interface MyOperation { String apply(String s); } String transform(String s, MyOperation mo) { String result = mo.apply(s) ; log(s + " : " + result); return result; } // Java 7 transform("Java8", new MyOperation() { @Override public String apply(String s) { return s.toUpperCase() ; } }); // Java 8 transform("Java8", s -> s.toUpperCase()) ;
  16. 16. Simplification 1 www.xsolve.plAgile Software House transform("Java8", s -> s.toUpperCase()) ; transform("Java8", String::toLowerCase ); transform("Java8", String::toUpperCase) ; transform("Java8", String::trim);
  17. 17. Simplification 2 (java.util.function) www.xsolve.plAgile Software House // before @FunctionalInterface interface MyOperation { String apply(String s); } String transform(String s, MyOperation mo) { String result = mo.apply(s) ; log(s + " : " + result); return result; } // after String transform(String s, UnaryOperator <String> uo) { String result = uo.apply(s) ; log(s + "<->" + result); return result; }
  18. 18. java.util.function www.xsolve.plAgile Software House INTERFACE METHOD Consumer<T> void accept(T t) Supplier<T> T get() Function<T, R> R apply(T t) UnaryOperator<T> T apply(T t) Predicate<T> boolean test(T t)
  19. 19. Lambdas summary www.xsolve.plAgile Software House ● Lambda syntax: (arg1, arg2) -> arg2.compareTo(arg1) ● Method references: String::length ● @FunctionalInterface ● java.util.function
  20. 20. www.xsolve.plAgile Software House
  21. 21. Streams
  22. 22. Streams - motivation www.xsolve.plAgile Software House ● C / C++ - arrays… ● Java / C# - Collections (List, Set…) ● Java 8 - Streams - Collections taken to another level!
  23. 23. Streams - example www.xsolve.plAgile Software House protected List<Book> books = new ArrayList<>(); public void init(){ String tolkien = "J.R.R. Tolkien"; String rowling = "J.K. Rowling"; String norris = "David Norris"; String theGod = "God Almighty"; books.addAll(Arrays.asList( new Book("The Lord of the Rings", tolkien, 1216), new Book("Silmarillion", tolkien, 365), new Book("Harry Potter and the Philosopher's Stone", rowling, 223), new Book("Harry Potter and the Half-Blood Prince", rowling, 554), new Book("Harry Potter and the Deathly Hallows", rowling, 607), new Book("Teach yourself Croatian", norris, 352), new Book("The Bible", theGod, 1200), new Book("The Hobbit", tolkien, 320) )); TODO: find out● the authors● of the top-3● thickest books● other than the Bible
  24. 24. Streams - example www.xsolve.plAgile Software House // 1. filter out the Bible List<Book> booksFiltered = new ArrayList<>(); for (Book book : books){ if (! "The Bible".equals(book.getTitle())) { booksFiltered.add(book); } } Java7 approach
  25. 25. Streams - example www.xsolve.plAgile Software House // 2. sort by number of pages, descending booksFiltered.sort(new Comparator<Book>() { @Override public int compare(Book o1, Book o2) { return o2.getPages().compareTo(o1.getPages()); } }); Java7 approach
  26. 26. Streams - example www.xsolve.plAgile Software House // 3. list the authors for (int i=0; i<3; i++) { System.out.println(booksFiltered.get(i).getAuthor()); } Java7 approach
  27. 27. Streams - example www.xsolve.plAgile Software House books.stream() .filter(b -> ! "The Bible".equals(b.getTitle())) .sorted((b1, b2) -> b2.getPages().compareTo(b1.getPages())) .limit(3) .map(Book::getAuthor) .distinct() .forEach(System.out::println); Streams to the rescue! TODO: find out● the authors● of the top-3● thickest books● other than the Bible
  28. 28. Streams - what are they? www.xsolve.plAgile Software House ● Interface: Stream<String>, Stream<Book>... ● NOT data structures ● Just wrappers around existing data sources (Collections, Files…) ● Do NOT modify the contents of the underlying data sources ● InputStream, ObjectInputStream, FileInputStream
  29. 29. Streams - characteristics www.xsolve.plAgile Software House ● Easily obtained from arrays or Collections List aList = new ArrayList(); aList.stream(); Collection aCollection = new LinkedHashSet<>(); aCollection.stream(); Integer[] anArray = {1, 2, 3, 4, 5}; Stream.of(anArray); // Stream<Integer> Stream.of("Hickory", "Dickory", "Dock"); // Stream<String> aList.stream().filter(o -> o != null); // Stream from another stream! Chaining!
  30. 30. Streams - characteristics www.xsolve.plAgile Software House ● Easily obtained from arrays or Collections ● ...and transformed into arrays or Collections List aList = aStream.collect(Collectors.toList()); Object[] anArray = aStream.toArray();
  31. 31. Streams - characteristics www.xsolve.plAgile Software House ● Easily obtained from arrays or Collections ● ...and transformed into arrays or Collections ● Designed for Lambdas aStream .filter(b -> ! "Moby Dick".equals(b.getTitle())) .sorted((b1, b2) -> b2.getPages().compareTo(b1.getPages())) .map(Book::getAuthor)
  32. 32. Streams - characteristics www.xsolve.plAgile Software House ● Easily obtained from arrays or Collections ● ...and transformed into arrays or Collections ● Designed for Lambdas ● Lazy (!)
  33. 33. Streams - characteristics www.xsolve.plAgile Software House ● Easily obtained from arrays or Collections ● ...and transformed into arrays or Collections ● Designed for Lambdas ● Lazy (!) ● Parallelizable (!!!) bookCollection.parallelStream().forEach(book -> { // do some badass long operation on the book } ); bookStream.parallel().forEach(book -> { // do some badass long operation on the book } );
  34. 34. Streams - core methods (1/3) www.xsolve.plAgile Software House ● forEach void forEach(Consumer) void forEachOrdered(Consumer) Stream.of("Facebook", "Google", "xSolve") .forEach(System.out::println); output? List<String> list = Arrays.asList("Facebook", "Google", "xSolve"); list.stream().forEach(String::toUpperCase); System.out.println(list); output? Stream.of("Facebook", "Google", "xSolve") .forEach(System.out::println).forEach Stream.of("Facebook", "Google", "xSolve") .forEach(System.out::println); output: Facebook Google xSolve List<String> list = Arrays.asList("Facebook", "Google", "xSolve"); list.stream().forEach(String::toUpperCase); System.out.println(list); output: [Facebook, Google, xSolve]
  35. 35. Streams - core methods (1/3) www.xsolve.plAgile Software House ● forEach void forEach(Consumer) void forEachOrdered(Consumer) ● map (mapToDouble, mapToInt, mapToLong) Stream map(Function mapper) Stream.of("Facebook", "Google", "xSolve") .map(str -> str.startsWith("x")) .forEach(System.out::println); output? int sum = Stream.of("1", "2", "3") .mapToInt(Integer::parseInt) .sum(); System.out.println(sum); output? Stream.of("Facebook", "Google", "xSolve") .map(str -> str.startsWith("x")) .forEach(System.out::println); output: false false true int sum = Stream.of("1", "2", "3") .mapToInt(Integer::parseInt) .sum(); System.out.println(sum); output: 6
  36. 36. Streams - core methods (1/3) www.xsolve.plAgile Software House ● forEach void forEach(Consumer) void forEachOrdered(Consumer) ● map (mapToDouble, mapToInt, mapToLong) Stream map(Function) ● filter Stream filter(Predicate) Stream.of("Facebook", "Google", "xSolve") .filter(str -> Character.isLowerCase(str.charAt(0))) .forEach(System.out::println); output? Stream.of("Facebook", "Google", "xSolve") .filter(str -> Character.isLowerCase(str.charAt(0))) .forEach(System.out::println); output: xSolve
  37. 37. Streams - core methods (2/3) www.xsolve.plAgile Software House ● findFirst Optional findFirst() String firstFound = Stream.of("Facebook", "Google", "xSolve") .filter(str -> str.contains("oo")) .findFirst() .get(); output? String notFound = Stream.of("Facebook", "Google", "xSolve") .filter(str -> str.contains("yay!")) .findFirst() .orElse("404 not found :("); System.out.println(notFound); output? String firstFound = Stream.of("Facebook", "Google", "xSolve") .filter(str -> str.contains("oo")) .findFirst() .get(); output: Facebook String notFound = Stream.of("Facebook", "Google", "xSolve") .filter(str -> str.contains("yay!")) .findFirst() .orElse("404 not found :("); System.out.println(notFound); output: 404 not found :(
  38. 38. Streams - core methods (2/3) www.xsolve.plAgile Software House ● findFirst Optional findFirst() ● findAny Optional findAny() String anyFound = Stream.of("Facebook", "Google", "xSolve") .parallel() .findAny() .get(); System.out.println(anyFound); output? String anyFound = Stream.of("Facebook", "Google", "xSolve") .parallel() .findAny() .get(); System.out.println(anyFound); output: Facebook or: Google or: xSolve
  39. 39. Streams - core methods (2/3) www.xsolve.plAgile Software House ● findFirst Optional findFirst() ● findAny Optional findAny() ● collect collect(Collector collector) List<String> uppers = Stream.of("cyan", "magenta", "yellow", "black") .map(String::toUpperCase) .collect(Collectors.toList()); System.out.println(uppers); output? List<String> uppers = Stream.of("cyan", "magenta", "yellow", "black") .map(String::toUpperCase) .collect(Collectors.toList()); System.out.println(uppers); output: [CYAN, MAGENTA, YELLOW, BLACK]
  40. 40. Streams - core methods (2/3) www.xsolve.plAgile Software House ● findFirst Optional findFirst() ● findAny Optional findAny() ● collect collect(Collector collector) ● toArray Object[] toArray() Object[] objArray = Stream.of("cyan", "magenta", "yellow", "black") .map(String::toUpperCase) .toArray(); String[] strArray = Stream.of("cyan", "magenta", "yellow", "black") .map(String::toUpperCase) .toArray(String[]::new);
  41. 41. Streams - core methods (3/3) www.xsolve.plAgile Software House ● Reduce T reduce(T starter, BinaryOperator) Optional reduce(BinaryOperator) String concatStarter = Stream.of("A", "n", "n", "a") .reduce("Lady ", String::concat); System.out.println(concatStarter); output? String concat = Stream.of("A", "n", "n", "a") .reduce(String::concat) .get(); System.out.println(concat); output? ❏ Stream → single value ❏ IntStream – min(), max(), sum(), average() String concatStarter = Stream.of("A", "n", "n", "a") .reduce("Lady ", String::concat); System.out.println(concatStarter); output: Lady Anna String concat = Stream.of("A", "n", "n", "a") .reduce(String::concat) .get(); System.out.println(concat); output: Anna
  42. 42. Streams - core methods (3/3) www.xsolve.plAgile Software House ● Reduce T reduce(T starter, BinaryOperator) Optional reduce(BinaryOperator) ● boolean allMatch(Predicate) boolean noneMatch(Predicate) boolean anyMatch(Predicate) boolean allMatch = Stream.of("Veronica", "Anna", "Patricia", "Alan", "Thomas") .allMatch(str -> str.endsWith("a")); System.out.println(allMatch); output? boolean noneMatch = Stream.of("Veronica", "Anna", "Patricia", "Alan", "Thomas") .noneMatch(str -> str.endsWith("a")); System.out.println(noneMatch); output? boolean anyMatch = Stream.of("Veronica", "Anna", "Patricia", "Alan", "Thomas") .anyMatch(str -> str.endsWith("a")); System.out.println(anyMatch); output? boolean allMatch = Stream.of("Veronica", "Anna", "Patricia", "Alan", "Thomas") .allMatch(str -> str.endsWith("a")); System.out.println(allMatch); output: false boolean noneMatch = Stream.of("Veronica", "Anna", "Patricia", "Alan", "Thomas") .noneMatch(str -> str.endsWith("a")); System.out.println(noneMatch); output: false boolean anyMatch = Stream.of("Veronica", "Anna", "Patricia", "Alan", "Thomas") .anyMatch(str -> str.endsWith("a")); System.out.println(anyMatch); output: true
  43. 43. Streams - core methods (3.5/3) www.xsolve.plAgile Software House ● long count() ● Stream sorted() ● Stream distinct() ● Stream limit(long maxSize) ● Stream skip(long n)
  44. 44. Streams - Terminal vs Non Terminal operations www.xsolve.plAgile Software House Terminal (consume a Stream) ● forEach, forEachOrdered ● toArray, reduce, collect ● min, max, count ● anyMatch, allMatch, noneMatch ● findFirst, findAny Non-terminal (return another Stream) ● map ● filter ● distinct, sorted ● peek ● limit, skip ● parallel, sequential, unordered Terminal (consume a Stream) ● forEach, forEachOrdered ● toArray, reduce, collect ● min, max, count ● anyMatch, allMatch, noneMatch ● findFirst, findAny Non-terminal (return another Stream) ● map ● filter ● distinct, sorted ● peek ● limit, skip ● parallel, sequential, unordered Short-circuit operations
  45. 45. Streams - lazy evaluation www.xsolve.plAgile Software House books.addAll(Arrays. asList( new Book("The Lord of the Rings" , tolkien, 1216), new Book("Silmarillion" , tolkien, 365), new Book("Harry Potter and something" , rowling, 223), new Book("Harry Potter and blahblah" , rowling, 554) // + 500k entries )); books.stream() .filter(it -> { System. out.println("name: " + nameFilterCounter ++); return "J.K. Rowling" .equals(it.getAuthor()) ; }) .filter(it -> { System. out.println("tpages: " + pageFilterCounter ++); return it.getPages() > 500; }) .findFirst() ; name: 0 name: 1 name: 2 pages: 0 name: 3 pages: 1 books.addAll(Arrays. asList( new Book("The Lord of the Rings" , tolkien, 1216), new Book("Silmarillion" , tolkien, 365), new Book("Harry Potter and something" , rowling, 223), new Book("Harry Potter and blahblah" , rowling, 554) // + 500k entries )); books.stream() .filter(it -> { System. out.println("name: " + nameFilterCounter ++); return "J.K. Rowling" .equals(it.getAuthor()) ; }) .filter(it -> { System. out.println("tpages: " + pageFilterCounter ++); return it.getPages() > 500; }) .findFirst(); ← short-circuit operation!
  46. 46. Streams - what you can’t do www.xsolve.plAgile Software House ● Reuse Stream stream = Stream.of("J", "a", "v", "a"); stream.filter(...).map(...) stream.map(...).forEach(...)
  47. 47. Streams - what you can’t do www.xsolve.plAgile Software House ● Reuse ● Change surrounding local variables int total = 0; Stream.of("Mercury", "Venus", "Mars") .forEach(str -> { total += str.length(); }); int[] total = {0}; Stream.of("Mercury", "Venus", "Mars") .forEach(str -> { total[0] += str.length(); }); ...but:
  48. 48. www.xsolve.plAgile Software House
  49. 49. File IO www.xsolve.plAgile Software House
  50. 50. www.xsolve.plAgile Software House File IO Java6 approach public void readFile() { File file = new File("/home/grzegorz/file.txt"); FileInputStream fis = null; try { fis = new FileInputStream(file); int content; while ((content = fis.read()) != -1) { System.out.print((char) content); } } catch (IOException e) { e.printStackTrace(); } finally { if (null != fis) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
  51. 51. www.xsolve.plAgile Software House File IO Java6 approach Java7 approach - java.lang.AutoCloseable - java.io.Closeable public void readFile() { File file = new File("/home/grzegorz/file.txt"); try (FileInputStream fis = new FileInputStream(file)) { int content; while ((content = fis.read()) != -1) { System.out.print((char) content); } } catch (IOException e) { e.printStackTrace(); } } public void readFile() { File file = new File("/home/grzegorz/file.txt"); FileInputStream fis = null; try { fis = new FileInputStream(file); int content; while ((content = fis.read()) != -1) { System.out.print((char) content); } } catch (IOException e) { e.printStackTrace(); } finally { if (null != fis) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
  52. 52. www.xsolve.plAgile Software House File IO public void readFile() { Path filePath = Paths.get("/home/grzegorz/file.txt"); try (Stream<String> stream = Files.lines(filePath)) { stream.forEach(System.out::print); } catch (IOException e) { e.printStackTrace(); } } Java8 approach public void readFile() { File file = new File("/home/grzegorz/file.txt"); try (FileInputStream fis = new FileInputStream(file)) { int content; while ((content = fis.read()) != -1) { System.out.print((char) content); } } catch (IOException e) { e.printStackTrace(); } } Java7 approach
  53. 53. www.xsolve.plAgile Software House File IO public void readFile() { File file = new File("/home/grzegorz/file.txt"); FileInputStream fis = null; try { fis = new FileInputStream(file); int content; while ((content = fis.read()) != -1) { System.out.print((char) content); } } catch (IOException e) { e.printStackTrace(); } finally { if (null != fis) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } Java6 approach public void readFile() { Path filePath = Paths.get("/home/grzegorz/file.txt"); try (Stream<String> stream = Files.lines(filePath)) { stream.forEach(System.out::print); } catch (IOException e) { e.printStackTrace(); } } Java8 approach vs.
  54. 54. www.xsolve.plAgile Software House File IO - Path vs. File “There is no one-to-one correspondence between the two APIs …” http://docs.oracle.com/javase/tutorial/essential/io/legacy.html
  55. 55. www.xsolve.plAgile Software House File IO - How to get Path? Path p1 = Paths.get("some-file.txt"); Path p2 = Paths.get("C:MyFolderanother-file.txt");
  56. 56. www.xsolve.plAgile Software House File IO - Methods of Path class Methods: toAbsolutePath, startsWith, endsWith, getFileName, getName, getNameCount, subpath, getParent, getRoot, normalize, relativize Sample Method Result toAbsolutePath C:eclipse-workspacejavafile-ioinput-file.txt getFileName input-file.tx getRoot C:
  57. 57. www.xsolve.plAgile Software House File IO - File.lines Stream<String> lines = Files.lines("some-path"); ● Can use all the cool and powerful Stream methods. ● Lazy evaluation. ● Throws IOException. ● Stream should be closed. ● Stream implements AutoCloseable
  58. 58. www.xsolve.plAgile Software House File IO - Example public List<Car> loadCars(Path filePath) { try (Stream<String> allCars = Files.lines(filePath)) { return allCars .filter(car -> hasFourSeats(car)) .filter(carWithFourSeats -> this::isRed) .map(redCarWithFourSeats -> addDoors(redCarWithFourSeats)) .sorted() .distinct() .collect(Collectors.toList()); } catch (IOException e) { e.printStackTrace(); } }
  59. 59. www.xsolve.plAgile Software House File IO - Files.write Files.write(somePath, lines, someCharset, someOption); Files.write(somePath, fileArray, someOption); ● somePath to file, ● lines e.g. List<String> lines, bytes[] data ● someCharset e.g. StandardCharsets.UTF_8 ● someOption e.q. StandardOpenOption.APPEND
  60. 60. www.xsolve.plAgile Software House File IO - Files.write Java7 approach public void savePoems(List<String> poems) { File file = new File("/home/grzegorz/poems.txt"); try (FileWriter fw = new FileWriter(file)) { for (String poem: poems) { fw.write(poem); } } catch (IOException e) { e.printStackTrace(); } }
  61. 61. www.xsolve.plAgile Software House File IO - Files.write Java7 approach public void savePoems(List<String> poems) { File file = new File("/home/grzegorz/poems.txt"); try (FileWriter fw = new FileWriter(file)) { for (String poem: poems) { fw.write(poem); } } catch (IOException e) { e.printStackTrace(); } } Java8 approach public void savePoems(List<String> poems) { Path path = Paths.get("/home/grzegorz/poems.txt"); try { Files.write(path, poems, StandardOpenOption.WRITE); } catch (IOException e) { e.printStackTrace(); } }
  62. 62. www.xsolve.plAgile Software House
  63. 63. www.xsolve.plAgile Software House ● Coreservlets.com, Marty Hall - “Java 8 Tutorial” http://www.coreservlets.com/java-8-tutorial/ ● Confitura 2015, Grzegorz Piwowarek - “Lambdas && Monads” (PL) https://youtu.be/VglEyjgxAKY More on Java8
  64. 64. www.xsolve.plAgile Software House You can find our job offers at xsolve.pl/career Thank you for your time! Questions? Marriage offers? Free lunch? team4java@xsolve.pl

×