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

Orientering Java 8 (SJ)

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on. →

Orientering Java 8 (SJ)

Avatar for Martin Andér Gottvall

Martin Andér Gottvall

December 21, 2016

Other Decks in Programming

Transcript

  1. Funktionella interface package java.util.function; @FunctionalInterface public interface Consumer<T> { /**

    * Performs this operation on the given argument. * * @param t the input argument */ void accept(T t); }
  2. implementerar alltid ett funktionellt interface Consumer<String> c1 = (String parameter)

    -> { System.out.println(parameter); }; Consumer<String> c2 = parameter -> System.out.println(parameter); Consumer<String> c3 = System.out::println;
  3. implementerar alltid ett funktionellt interface BiConsumer<String, Integer> bc1 = (String

    s, Integer i) -> this.foo(s, i); BiConsumer<String, Integer> bc2 = this::foo; BiFunction<String, Integer, Character> bf1 = (s, i) -> s.charAt(i); BiFunction<String, Integer, Character> bf2 = String::charAt; BiFunction<String, Integer, Character> bf3 = this::bar; // char bar(String s, Integer i)
  4. Variabler i måste vara “effectively final” int i = 0;

    Runnable incrementer = () -> i++; // Will not compile: // "Variable used in lambda should be final or effectively final" List<String> effectivelyFinalList = new ArrayList<>(); Runnable runnable = () -> effectivelyFinalList.add("add"); // Will compile List<String> nonFinalList = new ArrayList<>(); Runnable otherRunnable = () -> nonFinalList.add("add"); // Will not compile nonFinalList = new ArrayList<>();
  5. LambdaLab.java /* * For each exercise, develop a solution and

    remove the @Ignore tag. Then run the test. */ public class LambdaLab { // Exercise 1: Use an anonymous inner class to implement a Comparator<String> that sorts // strings by length (don't bother making it null safe) @Ignore @Test public void writeClassicComparator() { Comparator<String> comparator = null; assertEquals(6, comparator.compare("13 chars long", "7 chars")); assertEquals(-6, comparator.compare("7 chars", "13 chars long")); assertEquals(0, comparator.compare("same", "same"));
  6. LambdaLab.java • Hur gick det? • Lärde du dig något

    nytt? • Vad var lätt? Vad var svårt?
  7. Predicate @FunctionalInterface public interface Predicate<T> { /** * Evaluates this

    predicate on the given argument. * * @param t the input argument * @return {@code true} if the input argument matches the predicate, * otherwise {@code false} */ boolean test(T t); ... }
  8. Predicate Predicate<Integer> isOdd = integer -> integer % 2 !=

    0; System.out.println(isOdd.test(16)); // false Predicate<Integer> isSquare = integer -> Math.pow(Math.floor(Math.sqrt(integer)), 2) == integer; System.out.println(isSquare.test(16)); // true
  9. Predicate Predicate<Integer> isOdd = integer -> integer % 2 !=

    0; Predicate<Integer> isSquare = integer -> Math.pow(Math.floor(Math.sqrt(integer)), 2) == integer; System.out.println(isOdd.and(isSquare).test(16)); // false System.out.println(isOdd.and(isSquare).test(25)); // true System.out.println(isOdd.or(isSquare).test(16)); // true
  10. Predicate Predicate<Integer> isOdd = integer -> integer % 2 !=

    0; Predicate<Integer> isSquare = integer -> Math.pow(Math.floor(Math.sqrt(integer)), 2) == integer; System.out.println(isSquare.negate().test(16)); // false System.out.println(isOdd.negate().and(isSquare).test(16)); // true System.out.println((isOdd.and(isSquare)).negate().test(25)); // false
  11. Function @FunctionalInterface public interface Function<T, R> { /** * Applies

    this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t); ... }
  12. Function Function<Object, String> inBrackets = object -> "[" + String.valueOf(object)

    + "]"; System.out.println(inBrackets.apply("foo")); // [foo] Function<String, Integer> length = String::length; System.out.println(length.apply("foo")); // 3
  13. Function Function<Object, String> inBrackets = object -> "[" + String.valueOf(object)

    + "]"; Function<String, Integer> length = String::length; System.out.println(inBrackets.andThen(length).apply("foo")); // 5 System.out.println(inBrackets.compose(length).apply("foo")); // [3]
  14. PredicatesAndFunctionsLab.java /* * For each exercise, develop a solution and

    remove the @Ignore tag. Then run the test. */ public class PredicatesAndFunctionsLab { // Exercise 1: // * Write a function that doubles the value of a given integer // * Write a function that increases the value of a given integer by 5 @Test @Ignore public void basicIntegerFunctions() throws Exception { Function<Integer, Integer> doubler = null; // TODO Function<Integer, Integer> addFive = null; // TODO Assert.assertThat(doubler.apply(2), is(4));
  15. java.util.stream.* • En stream är inte en datastruktur som lagrar

    element • Funktionell • Minimerar arbete – “laziness-seeking” • Inte nödvändigtvis ändlig • Konsumerbar
  16. Skapa en stream • stream() eller parallelStream() på en Collection

    • Arrays.stream(Object[]) • Statiska factory-metoder t.ex. Stream.of(Object[]) • BufferedReader.lines() • Random.ints() , Random.doubles() etc
  17. Stream.filter() Stream<String> stream = Stream.of("foo", "bar", "baz"); Stream<String> filtered =

    stream.filter(s -> s.startsWith("b")); // {“bar”, “baz”}
  18. Stream.map() Person kristina = new Person("Kristina", 40, Arrays.asList("Stina", "Tina")); Person

    karl = new Person("Karl", 30, Arrays.asList("Kalle", "Kakan")); List<Person> persons = Arrays.asList(kristina, karl); Stream<Person> personStream = persons.stream(); // { Person: Kristina, Person: Karl } Stream<String> mapped = personStream.map(Person::getName); // { "Kristina", "Karl" }
  19. Några andra intermediära operationer .distinct() // filtrera ut dubletter baserat

    på equals() .sorted() // returnera en naturligt sorterad Stream .sorted(Comparator) // returnera en Stream som är sorterad enligt given Comparator .limit(long) // begränsa till angivet antal element .skip(long) // hoppa över angivet antal element
  20. Comparator.comparing List<Person> persons = Arrays.asList(new Person("Anna", 40), new Person("Anna", 35),

    new Person("Anna", 30), new Person("Lars", 25), new Person("Lars", 50)); Stream<Person> sortedByAge = persons.stream() .sorted(Comparator.comparing(Person::getAge)); // [Person: Lars 25, Person: Anna 30, Person: Anna 35, Person: Anna 40, Person: Lars 50] Stream<Person> sortedByNameThenAge = persons.stream() .sorted(Comparator.comparing(Person::getName) .thenComparing(Person::getAge)); // [Person: Anna 30, Person: Anna 35, Person: Anna 40, Person: Lars 25, Person: Lars 50]
  21. StreamsLab1.java /* * For each exercise, develop a solution using

    Java SE 8 Lambda/Streams * and remove the @Ignore tag. Then run the test. */ public class StreamsLab1 { // Exercise 1: Create a Stream of the words in the WORD_LIST constant that are shorter // than 4 characters @Test @Ignore public void filter() throws Exception { Stream<String> shorterThanFour = null; Assert.assertEquals("in, can, be, by, of", shorterThanFour.collect(Collectors.joining(", "))); }
  22. StreamsLab1.java • Hur gick det? • Lärde du dig något

    nytt? • Vad var lätt? Vad var svårt?
  23. Stream.map(), igen Person kristina = new Person("Kristina", 40, Arrays.asList("Stina", "Tina"));

    Person karl = new Person("Karl", 30, Arrays.asList("Kalle", "Kakan")); List<Person> persons = Arrays.asList(kristina, karl); persons.stream().map(Person::getNickNames); // ? Stream<List<String>> nickNames = persons.stream() .map(Person::getNickNames); // { ["Stina", "Tina"], // ["Kalle", "Kakan"] }
  24. Stream.flatMap() Person kristina = new Person("Kristina", 40, Arrays.asList("Stina", "Tina")); Person

    karl = new Person("Karl", 30, Arrays.asList("Kalle", "Kakan")); List<Person> persons = Arrays.asList(kristina, karl); Stream<String> flatMapped = persons.stream() .flatMap(name -> name.getNickNames() .stream()); // { "Stina", "Tina", "Kalle", "Kakan" }
  25. Stream.collect() Stream<T> stream = ...; List<T> list = stream.collect(Collectors.toList()); Set<T>

    set = stream.collect(Collectors.toCollection(HashSet::new)); String joined = stream.map(String::valueOf) .collect(Collectors.joining(", "));
  26. Stream.reduce() stream.collect(Collector) är ett specialfall av: <U> U reduce(U identity,

    BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
  27. Fler terminerande operationer Stream<String> stream = ...; Predicate<String> longStringPredicate =

    s -> s.length() > 5; Optional<String> findFirst = stream.filter(longStringPredicate) .findFirst(); Optional<String> findAny = stream.filter(longStringPredicate) .findAny(); boolean anyMatch = stream.anyMatch(longStringPredicate); boolean allMatch = stream.allMatch(longStringPredicate); long count = stream.count(); Optional<String> max = stream.max(Comparator) // största elementet, enligt given Comparator Optional<String> min = stream.min(Comparator) // minsta elementet, enligt given Comparator
  28. Siffervärden i stream IntStream range = IntStream.range(1, 10); // [1,

    2, 3, 4, 5, 6, 7, 8, 9] IntStream rangeClosed = IntStream.rangeClosed(1, 10); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] IntStream iterate = IntStream.iterate(1, i -> i^2 + i) .limit(4); // [1, 2, 6, 14]
  29. Siffervärden i stream IntStream range = IntStream.range(1, 10); OptionalDouble average

    = range.average(); OptionalInt max = range.max(); OptionalInt min = range.min(); int sum = range.sum(); IntSummaryStatistics statistics = range.summaryStatistics();
  30. Siffervärden i stream Stream<Person> stream = ...; Stream<Integer> ageStream =

    stream.map(Person::getAge); IntStream ageIntStream = stream.mapToInt(Person::getAge); Stream<Integer> ageStreamAgain = stream.mapToInt(Person::getAge) .boxed();
  31. Collectors.groupingBy() Stream<String> stream = Stream.of("AA", "AB", "ABB", "ABBA", "ABC", "ABF",

    "AC", "ACDC", "BASF", "BBC", "BC", "CBS", "CDRW", "CNN"); // {2=[AA, AB, AC, BC], 3=[ABB, ABC, ABF, BBC, CBS, CNN], 4=[ABBA, ACDC, BASF, CDRW]} Map<Integer, List<String>> mapByLength = stream.collect(Collectors.groupingBy(String::length));
  32. Collectors.groupingBy() Person kristina = new Person("Kristina", 40, Arrays.asList("Stina", "Tina")); Person

    karl = new Person("Karl", 30, Arrays.asList("Kalle", "Kakan")); Person anna = new Person("Anna", 30, new ArrayList<>()); Person lars = new Person("Lars", 40, Arrays.asList("Lasse")); Person sara = new Person("Sara", 40, Arrays.asList("Sasha")); List<Person> persons = Arrays.asList(kristina, karl, anna, lars, sara); // { // 40={1=[Person: Lars, Person: Sara], 2=[Person: Kristina]}, // 30={0=[Person: Anna], 2=[Person: Karl]} // } Map<Integer, Map<Integer, List<Person>>> mapByAgeAndNumberOfNicknames = persons.stream() .collect(Collectors.groupingBy(Person::getAge, Collectors.groupingBy( person -> person.getNickNames().size())));
  33. StreamsLab2.java /* * For each exercise, develop a solution using

    Java SE 8 Lambda/Streams * and remove the @Ignore tag. Then run the test. */ public class StreamsLab2 { // Exercise 1: Create a Stream of the words in the WORD_LIST constant that are shorter // than 4 characters @Test @Ignore public void filter() throws Exception { Stream<String> shorterThanFour = null; Assert.assertEquals("in, can, be, by, of", shorterThanFour.collect(Collectors.joining(", "))); }
  34. StreamsLab2.java • Hur gick det? • Lärde du dig något

    nytt? • Vad var lätt? Vad var svårt?
  35. Undvik sidoeffekter Stream<String> stream = Stream.of("foo", "bar", "baz"); // Don't

    do this List<String> usingSideEffect = new ArrayList<>(); stream.filter(s -> s.startsWith("b")) .forEach(usingSideEffect::add); // Do this instead List<String> usingReduce = stream.filter(s -> s.startsWith("b")) .collect(Collectors.toList());
  36. Optional<T> Optional<String> optional = ...; Optional<String> optionalLongString = optional.filter(string ->

    string.length() > 100); Optional<Integer> optionalInteger = optional.map(String::length); optional.ifPresent(this::doStuffWithString); // Side effects only, no return if (optional.isPresent()) { String value = optional.get(); // NoSuchElementException if not present! } String valueOrDefault = optional.orElse("default value");
  37. Interface default methods @FunctionalInterface public interface Function<T, R> { R

    apply(T t); default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } }
  38. Interface default methods Multipelt arv? NEJ! Komplieringsfel om en klass

    ärver metod med samma signatur från två olika interface. Klassen måste då implementera en egen version av metoden.
  39. java.time.* • Immutable och thread safe • Mycket likt org.joda.time

    • Mängder av statiska metoder för att skapa objekt med önskade egenskaper
  40. java.time.* • LocalDate: Dag, månad, år • LocalTime: Timme, minut,

    sekund (och nanosekund) • DateTime: Kombination av LocalDate och LocalTime • ZonedDateTime: DateTime + information om tidszon
  41. java.time.* LocalDate date = LocalDate.of(2016, 12, 24); // 2016-12-24 date

    = LocalDate.of(2016, Month.DECEMBER, 24); // 2016-12-24 date = LocalDate.parse("2016-12-24", DateTimeFormatter.ISO_LOCAL_DATE); // 2016-12-24 LocalTime time = LocalTime.of(15, 0); // 15:00 LocalDateTime dateTime = LocalDateTime.of(date, time); // 2016-12-24T15:00 ZoneId zone = ZoneId.of("Europe/Stockholm"); ZonedDateTime zoned = ZonedDateTime.of(dateTime, zone); // 2016-12-24T15:00+01:00[Europe/Stockholm]
  42. java.time.* LocalDate xmas = LocalDate.of(2016, Month.DECEMBER, 25); String isoFormatted =

    xmas.format(DateTimeFormatter.ISO_LOCAL_DATE); // 2016-12-25 String swedishFull = xmas.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)); // den 25 december 2016 String frenchShort = xmas.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT) .withLocale(Locale.FRANCE)); // 25/12/16 String fromPattern = xmas.format(DateTimeFormatter.ofPattern("w, MMM d yyyy")); // 51, dec 25 2016
  43. java.time.* LocalDate now = LocalDate.now(); LocalDate tomorrow = now.plusDays(1); LocalDate

    lastFridayThisMonth = now.with(TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY)); LocalDate firstDayOfNextMonth = now.with(TemporalAdjusters.firstDayOfNextMonth());
  44. java.time.* LocalDate xmas = LocalDate.of(2016, Month.DECEMBER, 25); String isoFormatted =

    xmas.format(DateTimeFormatter.ISO_LOCAL_DATE); // 2016-12-25 String swedishFull = xmas.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)); // den 25 december 2016 String frenchShort = xmas.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT) .withLocale(Locale.FRANCE)); // 25/12/16 String fromPattern = xmas.format(DateTimeFormatter.ofPattern("w, MMM d yyyy")); // 51, dec 25 2016
  45. java.time.* ZonedDateTime now = ZonedDateTime.now(); ZonedDateTime thirtyMinutesFromNow = now.plusMinutes(30); ZonedDateTime

    startOfCurrentHour = now.truncatedTo(ChronoUnit.HOURS); ZonedDateTime sameLocalTimeInNewYork = now.withZoneSameLocal(ZoneId.of("America/New_York"));
  46. java.time.* Instant before = Instant.now(); // Do stuff... Instant after

    = Instant.now(); System.out.println(Duration.between(before, after).toMillis());
  47. java.time.* Date date = new Date(); Instant instant = date.toInstant();

    Date backToDate = Date.from(instant); GregorianCalendar calendar = ...; ZonedDateTime zonedDateTime = calendar.toZonedDateTime(); GregorianCalendar backToCalendar = GregorianCalendar.from(zonedDateTime); TimeZone timeZone = calendar.getTimeZone(); ZoneId zoneId = timeZone.toZoneId(); TimeZone backToTimeZone = TimeZone.getTimeZone(zoneId);
  48. TimeLab.java /* * For each exercise, develop a solution using

    Java SE 8 Lambda/Streams * and remove the @Ignore tag. Then run the test. */ public class TimeLab { // Exercise 1: Print the current date and time in ISO 8601 format // (https://en.wikipedia.org/wiki/ISO_8601) @Test @Ignore public void printNow() { ZonedDateTime now = null; // TODO System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); System.out.println(now.format(DateTimeFormatter.ISO_DATE_TIME)); }
  49. TimeLab.java • Hur gick det? • Lärde du dig något

    nytt? • Vad var lätt? Vad var svårt?
  50. StringJoiner StringJoiner joiner = new StringJoiner(", ", "{", "}"); joiner.add("foo")

    .add("bar") .add("baz"); System.out.println(joiner.toString()); // {foo, bar, baz} List<String> stringList = Arrays.asList("foo", "bar", "baz"); System.out.println(stringList.stream() .collect(joining(", ", "{", "}"))); // {foo, bar, baz}
  51. Base64 String foo = "foo"; byte[] encoded = Base64.getEncoder().encode(foo.getBytes()); try

    { byte[] decoded = Base64.getDecoder().decode(encoded); } catch (IllegalArgumentException e) { // If argument is not valid base 64 } Base64.getMimeEncoder(); Base64.getMimeDecoder(); Base64.getUrlEncoder(); Base64.getUrlDecoder();
  52. Hur skulle ni kunna dra nytta av det som är

    nytt i Java 8? Var skulle det göra mest nytta?
  53. Hur skulle ni kunna dra nytta av det som är

    nytt i Java 8? Var skulle det göra mest nytta? Vad finns det för hinder för att införa mer Java 8-kod hos er?
  54. Tips för den som vill lära sig mer om Java

    8 • youtube: JavaOne, Devoxx, Jfokus • http://www.agiledeveloper.com/downloads.html
  55. IntelliJ-tips • IntelliJ är bra på att föreslå förenklingar av

    lambdauttryck • IntelliJ har ibland svårt när man mappar om typer i lambdauttryck • Terminera inte din Stream innan du är klar! • IntelliJ är pigg på att föreslå att traditionell kod kan ersättas med lambdauttryck
  56. Stream.filter() /** * Returns a stream consisting of the elements

    of this stream that match * the given predicate. * * This is an intermediate operation. * * @param predicate a non-interfering, stateless predicate to apply to each * element to determine if it should be included * @return the new stream */ Stream<T> filter(Predicate<? super T> predicate);
  57. Stream.map() /** * Returns a stream consisting of the results

    of applying the given * function to the elements of this stream. * * This is an intermediate operation. * * @param <R> The element type of the new stream * @param mapper a non-interfering, stateless function to apply to each element * @return the new stream */ <R> Stream<R> map(Function<? super T, ? extends R> mapper);