functional programming 1

Post on 14-Feb-2017

39 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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

1. Imperative style

2. Declarative style using list Arrays.asList(1, 2, 5, 4, 6, 5, 4, 3, 8)

3. Make inner methods

4. Add sout to methods to see amount of steps

5. Make method excluding findFirst().get() and explain lazy initialisation.

6. Show other ways to address to methods inside of others (through lightbulb)

7. Students try on their own do similar with IntStream

Get first doubled number greater than 3

Declarativeprivate 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 functionsprivate 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

IntStreamprivate 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 Implementationpublic 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 objects3. Make a team4. Collect all the languages they know

TDD + flatMap Implementation

public 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-multiple-foreach-with-casting

• Implement it using TDD

• Rewrite it into lambdas

• Check yourself

Maps + Sort1. 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/map.html

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

parameter1. 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 nothingTypes of functions in Java 8

Immutable and Mutable1. 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.

top related