Java 8: the good parts!

121
START

description

As presented at JavaOne session UGF10520 by me and @ktosopl

Transcript of Java 8: the good parts!

Page 1: Java 8: the good parts!

START

Page 2: Java 8: the good parts!

Movie Time!

Page 3: Java 8: the good parts!
Page 4: Java 8: the good parts!

Andrzej Grzesik Konrad Malawski

Page 5: Java 8: the good parts!

JAVA 8

Andrzej Grzesik Konrad Malawski

Page 6: Java 8: the good parts!

JAVA 8THE GOOD PARTS

Andrzej Grzesik Konrad Malawski

Page 8: Java 8: the good parts!

ABOUT:ME

Page 9: Java 8: the good parts!

 

Konrad `@ktosopl` Malawski

Page 10: Java 8: the good parts!

 

Konrad `@ktosopl` Malawski

Page 11: Java 8: the good parts!

OUR OPINIONSARE OUR OWN

disclaimer

Page 12: Java 8: the good parts!

QUESTIONS?

Page 13: Java 8: the good parts!

QUESTIONS?ask them right away!

Page 14: Java 8: the good parts!

JAVA 8 is going to be amazing!

Page 15: Java 8: the good parts!

TWITTER SAYS:

Page 16: Java 8: the good parts!

JAVA 8 IS THE NEW GUAVA

THE MOST EXCITING RELEASE IN HISTORY

Page 17: Java 8: the good parts!

DONE WITH COMMUNITY

Page 19: Java 8: the good parts!
Page 20: Java 8: the good parts!
Page 21: Java 8: the good parts!

YOU CAN HELP!

Page 22: Java 8: the good parts!

FIX TESTHACK

DOCUMENT

Page 23: Java 8: the good parts!

ADOPTOPENJDK.JAVA.NET

Page 24: Java 8: the good parts!

ADOPTAJSR.JAVA.NET

Page 25: Java 8: the good parts!

HOW DO I CHECK JDK8?

Page 26: Java 8: the good parts!

JDK8.JAVA.NET

Page 27: Java 8: the good parts!

IDE SUPPORT

Page 28: Java 8: the good parts!
Page 29: Java 8: the good parts!

JENVhttp://jenv.be

Page 30: Java 8: the good parts!

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)

Page 31: Java 8: the good parts!

JENV

ktoso @ 月/tmp$ jenv local oracle64-1.7.0.40

Page 32: Java 8: the good parts!

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

Page 33: Java 8: the good parts!

NEW TIME APIjsr 310

Page 34: Java 8: the good parts!

void immutable() { LocalTime aTime = LocalTime.now(); print("now: %s", aTime);

LocalTime newTime = aTime.plusMinutes(16); print("now: %s, later: %s", aTime, newTime); }

Page 35: Java 8: the good parts!

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

Page 36: Java 8: the good parts!

now: 01:25:56.916later: 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

Page 37: Java 8: the good parts!

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(); }

Page 38: Java 8: the good parts!

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); }

Page 39: Java 8: the good parts!

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

Page 40: Java 8: the good parts!

ISO BY DEFAULT

Page 41: Java 8: the good parts!

NO MOREnew SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");

Page 42: Java 8: the good parts!

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)); }

Page 43: Java 8: the good parts!

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

Page 44: Java 8: the good parts!

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

Page 45: Java 8: the good parts!

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.java:297)! (..)!*/ }

Page 47: Java 8: the good parts!

APIENHANCEMENTS

Page 48: Java 8: the good parts!

BETTER IO

Page 49: Java 8: the good parts!

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()}

Page 50: Java 8: the good parts!

MAPS

Page 51: Java 8: the good parts!

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) { // ... } }); }

Page 52: Java 8: the good parts!

void computeWithLambdas() { Map<Key, Value> map = // ...

map.computeIfAbsent(aKey, key -> { // ... });

map.computeIfPresent(aKey, (key, value) -> { // ... }); }

Page 53: Java 8: the good parts!

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)}

Page 54: Java 8: the good parts!

[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()); }

Page 55: Java 8: the good parts!

void parallelPrefix() { int[] array = { 1, 2, 4, 8 };

Arrays.parallelPrefix(array, (left, right) -> { return left + right; }); }

Page 56: Java 8: the good parts!

LAMBDAS?

Page 57: Java 8: the good parts!

LAMBDAS!(finally)

Page 58: Java 8: the good parts!

LAMBDAS

Notable inspirations would be:

ScalaGroovyLisps

.NOT (!)

Page 59: Java 8: the good parts!

() -> {}

LAMBDAS

Page 60: Java 8: the good parts!

LAMBDAS

(Thing t) -> {}

Page 61: Java 8: the good parts!

LAMBDAS

Page 62: Java 8: the good parts!

LAMBDAS

(Thing t) -> {}

Page 63: Java 8: the good parts!

LAMBDAS

(Thing t) -> {}

(Thing t, More m) -> {}

Page 64: Java 8: the good parts!

LAMBDAS & TYPES

Page 65: Java 8: the good parts!

LAMBDAS & TYPES

GetNum _ = (t) -> {42}

Page 66: Java 8: the good parts!

LAMBDAS & TYPES

GetNum _ = (t) -> {42}GetNum _ = (t) -> 42

Page 67: Java 8: the good parts!

LAMBDAS & TYPES

GetNum _ = (t) -> {42}GetNum _ = (t) -> 42GetNum _ = t -> 1337

Page 68: Java 8: the good parts!

interface Adder { void add(int a, int b);}

TARGET TYPING

Page 69: Java 8: the good parts!

interface Adder { void add(int a, int b);}

TARGET TYPING

Adder function = (int a, int b) -> { a + b };

Page 70: Java 8: the good parts!

interface Adder { void add(int a, int b);}

TARGET TYPING

Adder function = (int a, int b) -> { a + b };

Page 71: Java 8: the good parts!

interface Adder { void add(int a, int b);}

TARGET TYPING

Adder function = (int a, int b) -> { a + b };

(int, int) => int

gets converted into target type:

Adder

Page 72: Java 8: the good parts!

interface Adder { void add(int a, int b);}

TARGET TYPING

Adder function = (int a, int b) -> { a + b };

// or shorter:

Adder function = (a, b) -> a + b;

Page 73: Java 8: the good parts!

interface Adder { void add(int a, int b);}

TARGET TYPING

Adder function = (int a, int b) -> { a + b };

// or shorter:

Adder function = (a, b) -> a + b;

You can skip the ; sign!

Page 74: Java 8: the good parts!

interface Adder { void add(int a, int b);}

TARGET TYPING

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!

Page 75: Java 8: the good parts!

interface Adder { void add(int a, int b);}

TARGET TYPING

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!

Page 76: Java 8: the good parts!

FUNCTIONAL INTERFACES

interface Adder { void add(int a, int b);}

Page 77: Java 8: the good parts!

FUNCTIONAL INTERFACES

@FunctionalInterfaceinterface Adder { void add(int a, int b);}

Page 78: Java 8: the good parts!

FUNCTIONAL INTERFACES

@FunctionalInterfaceinterface Adder { void add(int a, int b);}

Similar to @Override: * not required,* checks our intent.

Page 79: Java 8: the good parts!

FUNCTIONAL INTERFACES

@FunctionalInterfaceinterface Adder { void add(int a, int b); void wat();}

Page 80: Java 8: the good parts!

FUNCTIONAL INTERFACES

@FunctionalInterfaceinterface 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

Page 81: Java 8: the good parts!

DEFAULT METHODS

@FunctionalInterfaceinterface Adder { void add(int a, int b); default void wat() { /* nothing... */ }}

OK!Only 1 abstract method.

Page 82: Java 8: the good parts!

DEFAULT METHODS@FunctionalInterfaceinterface Adder { default int add(int a, int b) { return a + b; }}

@FunctionalInterfaceinterface 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); }}

Page 83: Java 8: the good parts!

DEFAULT METHODS

We mixed in methods!

here! and here!

@FunctionalInterfaceinterface Adder { default int add(int a, int b) { return a + b; }}

@FunctionalInterfaceinterface 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); }}

Page 84: Java 8: the good parts!

interface A { default void doIt() { /* A */ }}

interface B { default void doIt() { /* B */ }}

class Thing implements A, B {}

DEFAULT METHODS

Page 85: Java 8: the good parts!

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

Page 86: Java 8: the good parts!

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!

Page 87: Java 8: the good parts!

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!

Page 88: Java 8: the good parts!

DEFAULT IN ITERABLEpackage java.lang;

@FunctionalInterfacepublic 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); } }

Page 89: Java 8: the good parts!

void withoutLambda() { button.addActionListener(new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { System.out.println("example"); } }); }

λ IN ACTION

Page 90: Java 8: the good parts!

BEFORE LAMBDASin IntelliJ

Page 91: Java 8: the good parts!

void withLambda() { button.addActionListener((e) -> { System.out.println("example"); }); }

λ IN ACTION

Page 92: Java 8: the good parts!

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);

}

Page 93: Java 8: the good parts!

REMOVING BOILERPLATE

Page 94: Java 8: the good parts!

STREAMS

Page 95: Java 8: the good parts!

void transform() { Iterables.transform( newArrayList(1, 2, 3), new Function<Integer, String>() { @Override public String apply(Integer input) { return input.toString(); } }); }

Page 96: Java 8: the good parts!

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

Page 97: Java 8: the good parts!

items.stream().map(Item::getName);

compared to Scala

items map { _.getName }

Page 98: Java 8: the good parts!

items.stream().map(Item::getName);

yay, we’re cool now!

compared to Scala

items map { _.getName }

Page 99: Java 8: the good parts!

STREAMS

items.stream().

filter(predicate); map(mapper); mapToInt(mapper); flatMap(mapper); distinct(); sorted(); sorted(comparator); peek(consumer); limit(maxSize); forEach(func);

Page 100: Java 8: the good parts!

INTERNAL ITERATION void internalIteration() { List<Thing> things = ...;

things.forEach(System.out::println); }

Page 101: Java 8: the good parts!

PARALLELIZE?

Page 102: Java 8: the good parts!

PARALLEL ITERATION

void parallelIteration() { List<Thing> things = ...;

things.parallelStream().forEach(System.out::println); }

Page 103: Java 8: the good parts!

STREAMS ARE LAZY!

Page 104: Java 8: the good parts!

List<Integer> is = newArrayList(1, 2, 3);

is.stream() .map(a -> printAndReturn("A", a)) .map(a -> printAndReturn("B", a));

STREAMS ARE LAZY

Page 105: Java 8: the good parts!

List<Integer> is = newArrayList(1, 2, 3);

is.stream() .map(a -> printAndReturn("A", a)) .map(a -> printAndReturn("B", a));

Prints:

STREAMS ARE LAZY

Page 106: Java 8: the good parts!

List<Integer> is = newArrayList(1, 2, 3);

is.stream() .map(a -> printAndReturn("A", a)) .map(a -> printAndReturn("B", a));

Prints:

STREAMS ARE LAZY

Nothing!

Page 107: Java 8: the good parts!

STREAMS ARE LAZYList<Integer> is = newArrayList(1, 2, 3);

is.stream() .map(a -> printAndReturn("A", a)) .map(a -> printAndReturn("B", a)) .collect(toList());

Page 108: Java 8: the good parts!

STREAMS ARE LAZYList<Integer> is = newArrayList(1, 2, 3);

is.stream() .map(a -> printAndReturn("A", a)) .map(a -> printAndReturn("B", a)) .collect(toList());

Prints:

A1B1A2B2A3B3

Page 109: Java 8: the good parts!

STREAMS ARE LAZYList<Integer> is = newArrayList(1, 2, 3);

is.stream() .map(a -> printAndReturn("A", a)) .map(a -> printAndReturn("B", a)) .collect(toList());

Prints:

A1B1A2B2A3B3

It’s ONE iteration!

Page 110: Java 8: the good parts!

METHOD HANDLESthink function pointers

Page 111: Java 8: the good parts!

KEEPING REFERENCES

??? method = Person::getName

class Person { String getName();}

?

Page 112: Java 8: the good parts!

KEEPING REFERENCES

Supplier<String> method = Person::getName

@FunctionalInterfacepublic interface Supplier<T> { T get();}

class Person { String getName();}

Page 113: Java 8: the good parts!

void referringToMethods() { String name = Person.getName();

String name = applyTo(heinz, Person::getName); }

Page 114: Java 8: the good parts!

REFERRING TO 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);}

Page 115: Java 8: the good parts!

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...!

Page 116: Java 8: the good parts!

Fact: in order to refer to:

String doThing(String a, String b, String c, Integer d);

JAVA.UTIL.FUNCTION.*

Page 117: Java 8: the good parts!

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.*

Page 118: Java 8: the good parts!

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.*

Page 120: Java 8: the good parts!

THANK YOU!

Page 121: Java 8: the good parts!

@ags313

Andrzej Grzesik Konrad Malawski

@ktosopl

TWEET PLEASE!