Functional Programming Lambda expressions in Java 8
Functional Programming • What is Functional Programming and Predicate (example from predicates logics of the first order). • It’s properties and peculiarities (no states and passing the control, one big function, no cycles)
Functional Programming - Definition • Функційне програмування є способом створення , ,програм в яких єдиною дією є виклик функції єдиним способом розбиття програми є створення нового імені функції та задання для ,цього імені виразу що обчислює значення ,функції а єдиним правилом композиції є .оператор суперпозиції функцій Жодних комірок ' , , , ,пам яті операторів присвоєння циклів ні тим , - .більше блок схем чи передачі управління
Determine if number is prime ( )простое 1. Write in good old Java 2. Write in Lambdas
IsPrime (imperative) /* * Imperative - how we do it * is mutable */ private static boolean isPrimeImperative(final int number) { for (int i = 2; i < number; i++) { if (number % i == 0) return false; } return true; }
IsPrime (declarative) /* * Declarative - what we do * is immutable */ private static boolean isPrimeDeclarative(final int number) { return IntStream.range(2, number).noneMatch(i -> number % i == 0); }
Get first doubled number greater than 3 Imperative style Declarative style using list Arrays.asList(1, 2, 5, 4, 6, 5, 4, 3, 8) Make inner methods Add sout to methods to see amount of steps Make method excluding findFirst().get() and explain lazy initialisation. Show other ways to address to methods inside of others (through lightbulb) Students try on their own do similar with IntStream
Get first doubled number greater than 3 Declarative private static int getEvenDoubledGreaterThanList(List<Integer> values, final int number) { return values.stream() .filter(i -> i > number) .filter(i -> i % 2 == 0) .map(i -> 2 * i) .findFirst().get();
Get first doubled number greater than 3 Declarative with functions private static int getEvenDoubledGreaterThanListSample(List<Integer> values, final int number) { return getEvenDoubleGreaterThan3Stream(values) .findFirst().get(); } private static Stream<Integer> getEvenDoubleGreaterThan3Stream(List<Integer> values) { return values.stream() .filter(FunctionalProgramming::isGreaterThan3 ) .filter(FunctionalProgramming::isEven) .map(FunctionalProgramming::doubleNumber); } private static Function<Integer, Integer> multiplyBy2() { return i -> 2 * i; } private static int doubleNumber(int number){ System.out.printf("nLet's double -> " + number); return number * 2; } private static Predicate<Integer> isEven() { return i -> i % 2 == 0; } private static boolean isEven(Integer number) { System.out.printf("nIs even -> " + number); return number % 2 == 0; } private static boolean isGreaterThan3(Integer number) { System.out.printf("nIs greater than 3 -> " + number); return number > 3; }
Get first doubled number greater than 3 with IntStream private static int getEvenDoubledGreaterThan(final int number) { return IntStream.range(number + 1, 100) .filter(i -> i % 2 == 0) .map(i -> 2 * i) .findFirst() .getAsInt(); }
Interface with one method 1. Create an interface with one boolean method. 2. Write realisation of the method: static OneMethodInterface cond1 = e -> e > 2; 3. Use it in filter 4. Students create similar stuff but with integer method: public int condition1 (int element);
Interface with one method Implementation public class Interfaces { // static OneMethodInterface cond1 = e -> e > 2; static OneMethodInterface cond2 = e -> e % 2; public static void main(String[] args) { call(cond2); } private static void call(OneMethodInterface interf) { // Stream.of(1, 3,2, 6,3,8).filter(i -> interf.condition(i)).forEach(i -> System.out.println(i)); // Stream.of(1, 3,2, 6,3,8).filter(interf::condition).forEach(i -> System.out.println(i)); Stream.of(1, 3,2, 6,3,8).map(interf::condition1).forEach(System.out::println); } public interface OneMethodInterface { // public boolean condition (int element); public int condition1 (int element); } }
Dependency Injection Using Strategy Pattern
Strategy Pattern in Old Java 1. Task: count total of List of integers 2. Add if statement to pick which values to sum using interface. 3. Create a Selector interface with one boolean method pick(int) and add it to total parameters. 4. Write realisation for the interface.
Strategy Pattern in Old Java Implementation public class InterfacesDI1 { public static void main(String[] args) { System.out.println(totalValues(Arrays.asList(1, 5, 3, 2, 8), new EvenSelector())); } public static int totalValues(List<Integer> values, Selector selector){ int sum = 0; for (Integer value : values) { if(selector.pick(value)) sum +=value; } return sum; } interface Selector{ public boolean pick(int element); } static class EvenSelector implements Selector{ @Override public boolean pick(int element) { return element % 2 == 0; } } }
Strategy Pattern in lambdas 1. Task: count total of List of integers 2. Change interface for Predicate 3. Write realisation of it’s test method instead of pick and use it 4. Rewrite total method into lambdas 5. Delete redundant
Strategy Pattern in lambdas Implementation public class InterfacesDI2 { public static void main(String[] args) { System.out.println(totalValues(Arrays.asList(1, 5, 3, 2, 8), e -> true)); System.out.println(totalValues(Arrays.asList(1, 5, 3, 2, 8), e -> e % 2 == 0)); } public static int totalValues(List<Integer> values, Predicate<Integer> selector) { return values.stream().filter(selector).reduce(0, Math::addExact); } }
TDD + flatMap 1. Task: using TDD write Developer object with name and list of languages. 2. Create several developer objects 3. Make a team 4. Collect all the languages they know
TDD + flatMap Implementationpublic class FlatMapTest { public static void main(String[] args) { FlatMapTest flatMapTest = new FlatMapTest(); flatMapTest.flatMap(); } @Test public void flatMap() { List<Developer> team = new ArrayList<>(); Developer polyglot = new Developer("esoteric"); polyglot.add("clojure"); polyglot.add("scala"); polyglot.add("groovy"); polyglot.add("go"); Developer busy = new Developer("pragmatic"); busy.add("java"); busy.add("javascript"); team.add(polyglot); team.add(busy); List<String> teamLanguages = team.stream(). map(d -> d.getLanguages()). flatMap(l -> l.stream()). collect(Collectors.toList()); System.out.println(teamLanguages); } private class Developer { String name; List<String> langs = new LinkedList<>(); public Developer(String name) { this.name = name; } private void add(String lang) { langs.add(lang); } private List<String> getLanguages() { return this.langs; } } }
Instance of public static void tryInstanceOf() { List<String> strings = Stream.of(1, 2.03, "Petit France", 3).filter(String.class::isInstance).map(String.class::cast).collect(Collectors.toList()); System.out.println("This is list " + strings); String string = Stream.of(1, 2.03, "Petit France", 3).filter(String.class::isInstance).map(String.class::cast).collect(Collectors.joining(",")); System.out.println("This is string " + string); Stream.of(1, 2.03, "Petit France", 3).filter(String.class::isInstance).map(String.class::cast).forEach(e -> System.out.println("This is string in lambdas for each " + e)); Stream.of(1, 2.03, "Petit France", 3).filter(Integer.class::isInstance).map(Integer.class::cast).forEach(System.out::println); Stream.of(1, 2.03, "Petit France", 3).filter(e -> e instanceof Double).map(e -> (Double) e).forEach(System.out::println); }
Home work • Copy-paste method in the task on this link in your code http://stackoverflow.com/questions/25439277/lambdas-mu • Implement it using TDD • Rewrite it into lambdas • Check yourself
Maps + Sort 1. Create a map and feel it with values 2. Try to sort it by values 3. Add writing to LinkedHashMap collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1, LinkedHashMap::new))); 4. Look https://docs.oracle.com/javase/tutorial/collections/interfaces/m
Maps + Sort Example public static void main(String[] args) { Map<Integer, String> map = new LinkedHashMap<>(); map.put(2, "2"); map.put(3, "3"); map.put(1, "1"); map.entrySet().stream().forEach(System.out::println); // map.entrySet().stream().forEach(e -> System.out.println(e)); System.out.println(map); System.out.println((Object) map.entrySet().stream().sorted((o1, o2) -> o2.getValue().compareTo(o1.getValue())). collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v2, LinkedHashMap::new))); }
Homework for sorting • Sort the cities and apartments in them in order of having the nearest free apartment starting form the given date.
Supplier or Lazy initialisation + empty parameter 1. Write method <R> R use(Supplier<R> mapper) 2. Use mapper.get in it 3. Write methods that use the method in the way use(() -> {…return …}); 4. Try return nothing 5. Return different parameters in «use» method and in the method that uses «use».
Consumer and other types of functions. • Takes an argument and returns nothing Types of functions in Java 8
Immutable and Mutable 1. Don't provide "setter" methods — methods that modify fields or objects referred to by fields. 2. Make all fields final and private. 3. Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods. 4. If the instance fields include references to mutable objects, don't allow those objects to be changed: - Don’t provide methods that modify the mutable objects. -Don’t share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.

Functional Programming

  • 1.
  • 2.
    Functional Programming • Whatis Functional Programming and Predicate (example from predicates logics of the first order). • It’s properties and peculiarities (no states and passing the control, one big function, no cycles)
  • 3.
    Functional Programming - Definition •Функційне програмування є способом створення , ,програм в яких єдиною дією є виклик функції єдиним способом розбиття програми є створення нового імені функції та задання для ,цього імені виразу що обчислює значення ,функції а єдиним правилом композиції є .оператор суперпозиції функцій Жодних комірок ' , , , ,пам яті операторів присвоєння циклів ні тим , - .більше блок схем чи передачі управління
  • 4.
    Determine if numberis prime ( )простое 1. Write in good old Java 2. Write in Lambdas
  • 5.
    IsPrime (imperative) /* * Imperative- how we do it * is mutable */ private static boolean isPrimeImperative(final int number) { for (int i = 2; i < number; i++) { if (number % i == 0) return false; } return true; }
  • 6.
    IsPrime (declarative) /* * Declarative- what we do * is immutable */ private static boolean isPrimeDeclarative(final int number) { return IntStream.range(2, number).noneMatch(i -> number % i == 0); }
  • 7.
    Get first doublednumber greater than 3 Imperative style Declarative style using list Arrays.asList(1, 2, 5, 4, 6, 5, 4, 3, 8) Make inner methods Add sout to methods to see amount of steps Make method excluding findFirst().get() and explain lazy initialisation. Show other ways to address to methods inside of others (through lightbulb) Students try on their own do similar with IntStream
  • 8.
    Get first doublednumber greater than 3 Declarative private static int getEvenDoubledGreaterThanList(List<Integer> values, final int number) { return values.stream() .filter(i -> i > number) .filter(i -> i % 2 == 0) .map(i -> 2 * i) .findFirst().get();
  • 9.
    Get first doublednumber greater than 3 Declarative with functions private static int getEvenDoubledGreaterThanListSample(List<Integer> values, final int number) { return getEvenDoubleGreaterThan3Stream(values) .findFirst().get(); } private static Stream<Integer> getEvenDoubleGreaterThan3Stream(List<Integer> values) { return values.stream() .filter(FunctionalProgramming::isGreaterThan3 ) .filter(FunctionalProgramming::isEven) .map(FunctionalProgramming::doubleNumber); } private static Function<Integer, Integer> multiplyBy2() { return i -> 2 * i; } private static int doubleNumber(int number){ System.out.printf("nLet's double -> " + number); return number * 2; } private static Predicate<Integer> isEven() { return i -> i % 2 == 0; } private static boolean isEven(Integer number) { System.out.printf("nIs even -> " + number); return number % 2 == 0; } private static boolean isGreaterThan3(Integer number) { System.out.printf("nIs greater than 3 -> " + number); return number > 3; }
  • 10.
    Get first doublednumber greater than 3 with IntStream private static int getEvenDoubledGreaterThan(final int number) { return IntStream.range(number + 1, 100) .filter(i -> i % 2 == 0) .map(i -> 2 * i) .findFirst() .getAsInt(); }
  • 11.
    Interface with onemethod 1. Create an interface with one boolean method. 2. Write realisation of the method: static OneMethodInterface cond1 = e -> e > 2; 3. Use it in filter 4. Students create similar stuff but with integer method: public int condition1 (int element);
  • 12.
    Interface with onemethod Implementation public class Interfaces { // static OneMethodInterface cond1 = e -> e > 2; static OneMethodInterface cond2 = e -> e % 2; public static void main(String[] args) { call(cond2); } private static void call(OneMethodInterface interf) { // Stream.of(1, 3,2, 6,3,8).filter(i -> interf.condition(i)).forEach(i -> System.out.println(i)); // Stream.of(1, 3,2, 6,3,8).filter(interf::condition).forEach(i -> System.out.println(i)); Stream.of(1, 3,2, 6,3,8).map(interf::condition1).forEach(System.out::println); } public interface OneMethodInterface { // public boolean condition (int element); public int condition1 (int element); } }
  • 13.
  • 14.
    Strategy Pattern inOld Java 1. Task: count total of List of integers 2. Add if statement to pick which values to sum using interface. 3. Create a Selector interface with one boolean method pick(int) and add it to total parameters. 4. Write realisation for the interface.
  • 15.
    Strategy Pattern inOld Java Implementation public class InterfacesDI1 { public static void main(String[] args) { System.out.println(totalValues(Arrays.asList(1, 5, 3, 2, 8), new EvenSelector())); } public static int totalValues(List<Integer> values, Selector selector){ int sum = 0; for (Integer value : values) { if(selector.pick(value)) sum +=value; } return sum; } interface Selector{ public boolean pick(int element); } static class EvenSelector implements Selector{ @Override public boolean pick(int element) { return element % 2 == 0; } } }
  • 16.
    Strategy Pattern inlambdas 1. Task: count total of List of integers 2. Change interface for Predicate 3. Write realisation of it’s test method instead of pick and use it 4. Rewrite total method into lambdas 5. Delete redundant
  • 17.
    Strategy Pattern inlambdas Implementation public class InterfacesDI2 { public static void main(String[] args) { System.out.println(totalValues(Arrays.asList(1, 5, 3, 2, 8), e -> true)); System.out.println(totalValues(Arrays.asList(1, 5, 3, 2, 8), e -> e % 2 == 0)); } public static int totalValues(List<Integer> values, Predicate<Integer> selector) { return values.stream().filter(selector).reduce(0, Math::addExact); } }
  • 18.
    TDD + flatMap 1.Task: using TDD write Developer object with name and list of languages. 2. Create several developer objects 3. Make a team 4. Collect all the languages they know
  • 19.
    TDD + flatMap Implementationpublicclass FlatMapTest { public static void main(String[] args) { FlatMapTest flatMapTest = new FlatMapTest(); flatMapTest.flatMap(); } @Test public void flatMap() { List<Developer> team = new ArrayList<>(); Developer polyglot = new Developer("esoteric"); polyglot.add("clojure"); polyglot.add("scala"); polyglot.add("groovy"); polyglot.add("go"); Developer busy = new Developer("pragmatic"); busy.add("java"); busy.add("javascript"); team.add(polyglot); team.add(busy); List<String> teamLanguages = team.stream(). map(d -> d.getLanguages()). flatMap(l -> l.stream()). collect(Collectors.toList()); System.out.println(teamLanguages); } private class Developer { String name; List<String> langs = new LinkedList<>(); public Developer(String name) { this.name = name; } private void add(String lang) { langs.add(lang); } private List<String> getLanguages() { return this.langs; } } }
  • 20.
    Instance of public staticvoid tryInstanceOf() { List<String> strings = Stream.of(1, 2.03, "Petit France", 3).filter(String.class::isInstance).map(String.class::cast).collect(Collectors.toList()); System.out.println("This is list " + strings); String string = Stream.of(1, 2.03, "Petit France", 3).filter(String.class::isInstance).map(String.class::cast).collect(Collectors.joining(",")); System.out.println("This is string " + string); Stream.of(1, 2.03, "Petit France", 3).filter(String.class::isInstance).map(String.class::cast).forEach(e -> System.out.println("This is string in lambdas for each " + e)); Stream.of(1, 2.03, "Petit France", 3).filter(Integer.class::isInstance).map(Integer.class::cast).forEach(System.out::println); Stream.of(1, 2.03, "Petit France", 3).filter(e -> e instanceof Double).map(e -> (Double) e).forEach(System.out::println); }
  • 21.
    Home work • Copy-pastemethod in the task on this link in your code http://stackoverflow.com/questions/25439277/lambdas-mu • Implement it using TDD • Rewrite it into lambdas • Check yourself
  • 22.
    Maps + Sort 1.Create a map and feel it with values 2. Try to sort it by values 3. Add writing to LinkedHashMap collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1, LinkedHashMap::new))); 4. Look https://docs.oracle.com/javase/tutorial/collections/interfaces/m
  • 23.
    Maps + SortExample public static void main(String[] args) { Map<Integer, String> map = new LinkedHashMap<>(); map.put(2, "2"); map.put(3, "3"); map.put(1, "1"); map.entrySet().stream().forEach(System.out::println); // map.entrySet().stream().forEach(e -> System.out.println(e)); System.out.println(map); System.out.println((Object) map.entrySet().stream().sorted((o1, o2) -> o2.getValue().compareTo(o1.getValue())). collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v2, LinkedHashMap::new))); }
  • 24.
    Homework for sorting •Sort the cities and apartments in them in order of having the nearest free apartment starting form the given date.
  • 25.
    Supplier or Lazyinitialisation + empty parameter 1. Write method <R> R use(Supplier<R> mapper) 2. Use mapper.get in it 3. Write methods that use the method in the way use(() -> {…return …}); 4. Try return nothing 5. Return different parameters in «use» method and in the method that uses «use».
  • 26.
    Consumer and othertypes of functions. • Takes an argument and returns nothing Types of functions in Java 8
  • 27.
    Immutable and Mutable 1.Don't provide "setter" methods — methods that modify fields or objects referred to by fields. 2. Make all fields final and private. 3. Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods. 4. If the instance fields include references to mutable objects, don't allow those objects to be changed: - Don’t provide methods that modify the mutable objects. -Don’t share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.