Java 8: the good parts!

6,832 views
6,778 views

Published on

As presented at JavaOne session UGF10520 by me and @ktosopl

Published in: Technology, News & Politics
1 Comment
10 Likes
Statistics
Notes
  • Great insight to java 8 features. Thanks for the presentation
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
6,832
On SlideShare
0
From Embeds
0
Number of Embeds
293
Actions
Shares
0
Downloads
173
Comments
1
Likes
10
Embeds 0
No embeds

No notes for slide

Java 8: the good parts!

  1. 1. START
  2. 2. MovieTime!
  3. 3. Andrzej Grzesik Konrad Malawski
  4. 4. JAVA 8 Andrzej Grzesik Konrad Malawski
  5. 5. JAVA 8 THE GOOD PARTS Andrzej Grzesik Konrad Malawski
  6. 6. @ags313 andrzej@grzesik.it andrzejgrzesik.info Andrzej Grzesik
  7. 7. ABOUT:ME
  8. 8.   Konrad `@ktosopl` Malawski
  9. 9.   Konrad `@ktosopl` Malawski
  10. 10. OUR OPINIONS ARE OUR OWN disclaimer
  11. 11. QUESTIONS?
  12. 12. QUESTIONS? ask them right away!
  13. 13. JAVA 8 is going to be amazing!
  14. 14. TWITTER SAYS:
  15. 15. JAVA 8 ISTHE NEW GUAVA THE MOST EXCITING RELEASE IN HISTORY
  16. 16. DONE WITH COMMUNITY
  17. 17. ADOPT OPENJDK adoptopenjdk.java.net
  18. 18. YOU CAN HELP!
  19. 19. FIX TEST HACK DOCUMENT
  20. 20. ADOPTOPENJDK.JAVA.NET
  21. 21. ADOPTAJSR.JAVA.NET
  22. 22. HOW DO I CHECK JDK8?
  23. 23. JDK8.JAVA.NET
  24. 24. IDE SUPPORT
  25. 25. JENV http://jenv.be
  26. 26. JENV $ jenv versions system oracle64-1.6.0.51 oracle64-1.7.0.40 * oracle64-1.8.0-ea (set by /Users/ktoso/.jenv/version)
  27. 27. JENV ktoso @ 月/tmp $ jenv local oracle64-1.7.0.40
  28. 28. JENV ktoso @ 月/tmp $ jenv versions systema oracle64-1.6.0.51 * oracle64-1.7.0.40 (set by /tmp/.java-version) oracle64-1.8.0-ea ktoso @ 月/tmp $ jenv local oracle64-1.7.0.40
  29. 29. NEWTIME API jsr 310
  30. 30. void immutable() { LocalTime aTime = LocalTime.now(); print("now: %s", aTime); LocalTime newTime = aTime.plusMinutes(16); print("now: %s, later: %s", aTime, newTime); }
  31. 31. void immutable() { LocalTime aTime = LocalTime.now(); print("now: %s", aTime); LocalTime newTime = aTime.plusMinutes(16); print("now: %s, later: %s", aTime, newTime); } now: 01:25:56.916
  32. 32. now: 01:25:56.916 later: 01:41:56.916 void immutable() { LocalTime aTime = LocalTime.now(); print("now: %s", aTime); LocalTime newTime = aTime.plusMinutes(16); print("now: %s, later: %s", aTime, newTime); } now: 01:25:56.916
  33. 33. private void localTime() { LocalDate today = LocalDate.now(); LocalDate yesterday = today.minusDays(1); // Geek Bike Ride! LocalDateTime localDateTime = yesterday.atTime(11, 30); LocalDateTime earlyMorning = LocalDate.of(2013, 9, 22) .atStartOfDay(); }
  34. 34. void flightTime() { ZoneId LHR = ZoneId.of("Europe/London"); ZoneId SFO = ZoneId.of("America/Los_Angeles"); LocalDate date = LocalDate.of(2013, Month.SEPTEMBER, 14); LocalTime takeoff = LocalTime.of(12, 50); LocalTime landing = LocalTime.of(16, 20); Duration flightTime = Duration.between( ZonedDateTime.of(date, takeoff, LHR), ZonedDateTime.of(date, landing, SFO)); System.out.println("Flight time: " + flightTime); }
  35. 35. void flightTime() { ZoneId LHR = ZoneId.of("Europe/London"); ZoneId SFO = ZoneId.of("America/Los_Angeles"); LocalDate date = LocalDate.of(2013, Month.SEPTEMBER, 14); LocalTime takeoff = LocalTime.of(12, 50); LocalTime landing = LocalTime.of(16, 20); Duration flightTime = Duration.between( ZonedDateTime.of(date, takeoff, LHR), ZonedDateTime.of(date, landing, SFO)); System.out.println("Flight time: " + flightTime); } Flight time: PT11H30M
  36. 36. ISO BY DEFAULT
  37. 37. NO MORE new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
  38. 38. void formatting() { DateTimeFormatter.ISO_DATE. format(LocalDateTime.of(2013, 9, 22, 10, 03)); DateTimeFormatter.ISO_DATE_TIME. format(LocalDateTime.of(2013, 9, 22, 10, 30)); }
  39. 39. void formatting() { DateTimeFormatter.ISO_DATE. format(LocalDateTime.of(2013, 9, 22, 10, 03)); DateTimeFormatter.ISO_DATE_TIME. format(LocalDateTime.of(2013, 9, 22, 10, 30)); } 2013-09-22
  40. 40. void formatting() { DateTimeFormatter.ISO_DATE. format(LocalDateTime.of(2013, 9, 22, 10, 03)); DateTimeFormatter.ISO_DATE_TIME. format(LocalDateTime.of(2013, 9, 22, 10, 30)); } 2013-09-22 2013-09-22T10:30:00
  41. 41. void formatterError() { ISO_DATE_TIME.format(LocalDate.of(2013, 9, 22)); /* Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: HourOfDay ! at java.time.LocalDate.get0(LocalDate.java:670) ! at java.time.LocalDate.getLong(LocalDate.java:649) ! at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.ja va:297) ! (..)! */ }
  42. 42. TUTORIAL http://docs.oracle.com/javase/tutorial/datetime/index.html
  43. 43. API ENHANCEMENTS
  44. 44. BETTER IO
  45. 45. void betterIO() { BufferedReader bufferedReader; Path path; Stream<String> lines = bufferedReader.lines(); Stream<String> lines = Files.lines(Path, Charset); Stream<Path> paths = Files.list(Path); Stream<Path> paths = Files.find(Path, depth, BiPredicate, FileVisitOption...) Stream<Path> paths = Files.walk(Path, depth, FileVisitOption...) Stream<Path> paths = Files.walk(Path, FileVisitOption...) DirectoryStream.stream() }
  46. 46. MAPS
  47. 47. compute() { map.compute(aKey, new BiFunction<Key, Value, Value>() { @Override public Value apply(Key key, Value value) { // ... } }); map.computeIfAbsent(aKey, new Function<Key, Value>() { @Override public Value apply(Key key) { // ... } }); map.computeIfPresent(aKey, new BiFunction<Key, Value, Value>() { @Override public Value apply(Key key, Value value) { // ... } }); }
  48. 48. void computeWithLambdas() { Map<Key, Value> map = // ... map.computeIfAbsent(aKey, key -> { // ... }); map.computeIfPresent(aKey, (key, value) -> { // ... }); }
  49. 49. void moreMaps() { Map<Key, Value> map = null; map.putIfAbsent(K, V); map.remove(Object, Object); map.replace(K, V); // Compare and swap map.replace(K, V1, V2); map.replaceAll(BiFunction); map.getOrDefault(K, V); map.merge(K, V, BiFunction) }
  50. 50. [5, 8, 6, 7, 2, 1, 4, 3] void parallelSetAll() { int[] array = new int[8]; AtomicInteger i = new AtomicInteger(); Arrays.parallelSetAll(array, operand -> i.incrementAndGet()); }
  51. 51. void parallelPrefix() { int[] array = { 1, 2, 4, 8 }; Arrays.parallelPrefix(array, (left, right) -> { return left + right; }); }
  52. 52. LAMBDAS?
  53. 53. LAMBDAS! (finally)
  54. 54. LAMBDAS Notable inspirations would be: Scala Groovy Lisps .NOT (!)
  55. 55. () -> {} LAMBDAS
  56. 56. LAMBDAS (Thing t) -> {}
  57. 57. LAMBDAS
  58. 58. LAMBDAS (Thing t) -> {}
  59. 59. LAMBDAS (Thing t) -> {} (Thing t, More m) -> {}
  60. 60. LAMBDAS &TYPES
  61. 61. LAMBDAS &TYPES GetNum _ = (t) -> {42}
  62. 62. LAMBDAS &TYPES GetNum _ = (t) -> {42} GetNum _ = (t) -> 42
  63. 63. LAMBDAS &TYPES GetNum _ = (t) -> {42} GetNum _ = (t) -> 42 GetNum _ = t -> 1337
  64. 64. interface Adder { void add(int a, int b); } TARGETTYPING
  65. 65. interface Adder { void add(int a, int b); } TARGETTYPING Adder function = (int a, int b) -> { a + b };
  66. 66. interface Adder { void add(int a, int b); } TARGETTYPING Adder function = (int a, int b) -> { a + b };
  67. 67. interface Adder { void add(int a, int b); } TARGETTYPING Adder function = (int a, int b) -> { a + b }; (int, int) => int gets converted into target type: Adder
  68. 68. interface Adder { void add(int a, int b); } TARGETTYPING Adder function = (int a, int b) -> { a + b }; // or shorter: Adder function = (a, b) -> a + b;
  69. 69. interface Adder { void add(int a, int b); } TARGETTYPING Adder function = (int a, int b) -> { a + b }; // or shorter: Adder function = (a, b) -> a + b; You can skip the ; sign!
  70. 70. interface Adder { void add(int a, int b); } TARGETTYPING Adder function = (int a, int b) -> { a + b }; // or shorter: Adder function = (a, b) -> a + b; You can skip { } sometimes You can skip the ; sign!
  71. 71. interface Adder { void add(int a, int b); } TARGETTYPING Adder function = (int a, int b) -> { a + b }; // or shorter: Adder function = (a, b) -> a + b; You can skip { } sometimes You can skip the ; sign! and the types are inferred!
  72. 72. FUNCTIONAL INTERFACES interface Adder { void add(int a, int b); }
  73. 73. FUNCTIONAL INTERFACES @FunctionalInterface interface Adder { void add(int a, int b); }
  74. 74. FUNCTIONAL INTERFACES @FunctionalInterface interface Adder { void add(int a, int b); } Similar to @Override: * not required, * checks our intent.
  75. 75. FUNCTIONAL INTERFACES @FunctionalInterface interface Adder { void add(int a, int b); void wat(); }
  76. 76. FUNCTIONAL INTERFACES @FunctionalInterface interface Adder { void add(int a, int b); void wat(); } java: Unexpected @FunctionalInterface annotation pl.project13.lambda.test.examples.Adder is not a functional interface multiple non-overriding abstract methods found in interface pl.project13.lambda.test.examples.Adder
  77. 77. DEFAULT METHODS @FunctionalInterface interface Adder { void add(int a, int b); default void wat() { /* nothing... */ } } OK! Only 1 abstract method.
  78. 78. DEFAULT METHODS @FunctionalInterface interface Adder { default int add(int a, int b) { return a + b; } } @FunctionalInterface interface Divider { default double divide(int a, int b) { return a / b; } } class Calculator implements Adder, Divider { public double calc(int a, int b, int c) { return divide(add(a, b), c); } }
  79. 79. DEFAULT METHODS We mixed in methods! here! and here! @FunctionalInterface interface Adder { default int add(int a, int b) { return a + b; } } @FunctionalInterface interface Divider { default double divide(int a, int b) { return a / b; } } class Calculator implements Adder, Divider { public double calc(int a, int b, int c) { return divide(add(a, b), c); } }
  80. 80. interface A { default void doIt() { /* A */ } } interface B { default void doIt() { /* B */ } } class Thing implements A, B { } DEFAULT METHODS
  81. 81. interface A { default void doIt() { /* A */ } } interface B { default void doIt() { /* B */ } } class Thing implements A, B { } DEFAULT METHODS java: class com.javaone.Thing inherits unrelated defaults for doIt() from types com.javaone.A and com.javaone.B
  82. 82. DEFAULT METHODS interface A { default void doIt() { /* A */ } } interface B { default void doIt() { /* B */ } } class Thing implements A, B { @Override public void doIt() { A.super.doIt(); } } Resolve ambiguity manually!
  83. 83. DEFAULT METHODS interface A { default void doIt() { /* A */ } } interface B { default void doIt() { /* B */ } } class Thing implements A, B { @Override public void doIt() { A.super.doIt(); } } Resolve ambiguity manually!
  84. 84. DEFAULT IN ITERABLE package java.lang; @FunctionalInterface public interface Iterable<T> { Iterator<T> iterator(); /** @since 1.8 */ default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } }
  85. 85. void withoutLambda() { button.addActionListener(new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { System.out.println("example"); } }); } λ IN ACTION
  86. 86. BEFORE LAMBDAS in IntelliJ
  87. 87. void withLambda() { button.addActionListener((e) -> { System.out.println("example"); }); } λ IN ACTION
  88. 88. void composingFunctions() { // given Function<Integer, Integer> timesTwo = n -> n * 2; Function<Integer, Integer> plusOne = n -> n + 1; // when Function<Integer, Integer> multiplyThenAdd = timesTwo.andThen(plusOne); // equivalent to Function<Integer, Integer> multiplyThenAdd = plusOne.compose(timesTwo); // then int result = multiplyThenAdd.apply(1); assertThat(result).isEqualTo(3); }
  89. 89. REMOVING BOILERPLATE
  90. 90. STREAMS
  91. 91. void transform() { Iterables.transform( newArrayList(1, 2, 3), new Function<Integer, String>() { @Override public String apply(Integer input) { return input.toString(); } }); }
  92. 92. void transform() { Iterables.transform( newArrayList(1, 2, 3), new Function<Integer, String>() { @Override public String apply(Integer input) { return input.toString(); } }); } void noMoreTransform() { items.stream().map(i -> i.toString()); } vs
  93. 93. items.stream().map(Item::getName); compared to Scala items map { _.getName }
  94. 94. items.stream().map(Item::getName); yay, we’re cool now! compared to Scala items map { _.getName }
  95. 95. STREAMS items.stream(). filter(predicate); map(mapper); mapToInt(mapper); flatMap(mapper); distinct(); sorted(); sorted(comparator); peek(consumer); limit(maxSize); forEach(func);
  96. 96. INTERNAL ITERATION void internalIteration() { List<Thing> things = ...; things.forEach(System.out::println); }
  97. 97. PARALLELIZE?
  98. 98. PARALLEL ITERATION void parallelIteration() { List<Thing> things = ...; things.parallelStream().forEach(System.out::println); }
  99. 99. STREAMS ARE LAZY!
  100. 100. List<Integer> is = newArrayList(1, 2, 3); is.stream() .map(a -> printAndReturn("A", a)) .map(a -> printAndReturn("B", a)); STREAMS ARE LAZY
  101. 101. List<Integer> is = newArrayList(1, 2, 3); is.stream() .map(a -> printAndReturn("A", a)) .map(a -> printAndReturn("B", a)); Prints: STREAMS ARE LAZY
  102. 102. List<Integer> is = newArrayList(1, 2, 3); is.stream() .map(a -> printAndReturn("A", a)) .map(a -> printAndReturn("B", a)); Prints: STREAMS ARE LAZY Nothing!
  103. 103. STREAMS ARE LAZY List<Integer> is = newArrayList(1, 2, 3); is.stream() .map(a -> printAndReturn("A", a)) .map(a -> printAndReturn("B", a)) .collect(toList());
  104. 104. STREAMS ARE LAZY List<Integer> is = newArrayList(1, 2, 3); is.stream() .map(a -> printAndReturn("A", a)) .map(a -> printAndReturn("B", a)) .collect(toList()); Prints: A1 B1 A2 B2 A3 B3
  105. 105. STREAMS ARE LAZY List<Integer> is = newArrayList(1, 2, 3); is.stream() .map(a -> printAndReturn("A", a)) .map(a -> printAndReturn("B", a)) .collect(toList()); Prints: A1 B1 A2 B2 A3 B3 It’s ONE iteration!
  106. 106. METHOD HANDLES think function pointers
  107. 107. KEEPING REFERENCES ??? method = Person::getName class Person { String getName(); } ?
  108. 108. KEEPING REFERENCES Supplier<String> method = Person::getName @FunctionalInterface public interface Supplier<T> { T get(); } class Person { String getName(); }
  109. 109. void referringToMethods() { String name = Person.getName(); String name = applyTo(heinz, Person::getName); }
  110. 110. REFERRINGTO METHODS String normalName = heinz.getName(); String magicName = applyTo(heinz, Person::getName); public <T, R> R applyTo(T obj, Function<T, R> function) { return function.apply(obj); }
  111. 111. JAVA.UTIL.FUNCTION.* Supplier<T> => T Consumer<T> T => void Predicate<T> T => Boolean BiPredicate<T1, T2> (T1, T2) => Boolean Function<T, R> T => R BiFunction<T1, T2, R> (T1, T2) => R and more...!
  112. 112. Fact: in order to refer to: String doThing(String a, String b, String c, Integer d); JAVA.UTIL.FUNCTION.*
  113. 113. Fact: in order to refer to: String doThing(String a, String b, String c, Integer d); you have to: @FunctionalInterface interface Function4<T1, T2, T3, T4, R> { R apply(T1 a, T2 b, T3 c, T4 d); } JAVA.UTIL.FUNCTION.*
  114. 114. Fact: in order to refer to: String doThing(String a, String b, String c, Integer d); you have to: @FunctionalInterface interface Function4<T1, T2, T3, T4, R> { R apply(T1 a, T2 b, T3 c, T4 d); } Function4<String, String, String, Integer, String> fun = Example::doThing; JAVA.UTIL.FUNCTION.*
  115. 115. BACKTOTHE FUTURE! ● http://cr.openjdk.java.net/~briangoetz/ lambda/collections-overview.html ● http://docs.oracle.com/javase/tutorial/java/javaOO/ lambdaexpressions.html ● http://www.techempower.com/blog/2013/03/26/ everything-about-java-8/ ● For fun, Lambda Spec: github.com/ktoso/lambda-spec
  116. 116. THANKYOU!
  117. 117. @ags313 Andrzej Grzesik Konrad Malawski @ktosopl TWEET PLEASE!

×