JavaOne 2013: Java 8 - The Good Parts

121
START

description

This talk was delivered at JavaOne 2013, together with Andrzej Grzesik. We mention the new Date APIs, changes to Collections as well as Streams APIs and of course... Lambdas!

Transcript of JavaOne 2013: Java 8 - The Good Parts

Page 1: JavaOne 2013: Java 8 - The Good Parts

START

Page 2: JavaOne 2013: Java 8 - The Good Parts

Movie Time!

Page 3: JavaOne 2013: Java 8 - The Good Parts
Page 4: JavaOne 2013: Java 8 - The Good Parts

Andrzej Grzesik Konrad Malawski

Page 5: JavaOne 2013: Java 8 - The Good Parts

JAVA 8

Andrzej Grzesik Konrad Malawski

Page 6: JavaOne 2013: Java 8 - The Good Parts

JAVA 8THE GOOD PARTS

Andrzej Grzesik Konrad Malawski

Page 8: JavaOne 2013: Java 8 - The Good Parts

ABOUT:ME

Page 9: JavaOne 2013: Java 8 - The Good Parts

 

Konrad `@ktosopl` Malawski

Page 10: JavaOne 2013: Java 8 - The Good Parts

 

Konrad `@ktosopl` Malawski

Page 11: JavaOne 2013: Java 8 - The Good Parts

OUR OPINIONSARE OUR OWN

disclaimer

Page 12: JavaOne 2013: Java 8 - The Good Parts

QUESTIONS?

Page 13: JavaOne 2013: Java 8 - The Good Parts

QUESTIONS?ask them right away!

Page 14: JavaOne 2013: Java 8 - The Good Parts

JAVA 8 is going to be amazing!

Page 15: JavaOne 2013: Java 8 - The Good Parts

TWITTER SAYS:

Page 16: JavaOne 2013: Java 8 - The Good Parts

JAVA 8 IS THE NEW GUAVA

THE MOST EXCITING RELEASE IN HISTORY

Page 17: JavaOne 2013: Java 8 - The Good Parts

DONE WITH COMMUNITY

Page 19: JavaOne 2013: Java 8 - The Good Parts
Page 20: JavaOne 2013: Java 8 - The Good Parts
Page 21: JavaOne 2013: Java 8 - The Good Parts

YOU CAN HELP!

Page 22: JavaOne 2013: Java 8 - The Good Parts

FIX TESTHACK

DOCUMENT

Page 23: JavaOne 2013: Java 8 - The Good Parts

ADOPTOPENJDK.JAVA.NET

Page 24: JavaOne 2013: Java 8 - The Good Parts

ADOPTAJSR.JAVA.NET

Page 25: JavaOne 2013: Java 8 - The Good Parts

HOW DO I CHECK JDK8?

Page 26: JavaOne 2013: Java 8 - The Good Parts

JDK8.JAVA.NET

Page 27: JavaOne 2013: Java 8 - The Good Parts

IDE SUPPORT

Page 28: JavaOne 2013: Java 8 - The Good Parts
Page 29: JavaOne 2013: Java 8 - The Good Parts

JENVhttp://jenv.be

Page 30: JavaOne 2013: 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: JavaOne 2013: Java 8 - The Good Parts

JENV

ktoso @ 月/tmp$ jenv local oracle64-1.7.0.40

Page 32: JavaOne 2013: 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: JavaOne 2013: Java 8 - The Good Parts

NEW TIME APIjsr 310

Page 34: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: Java 8 - The Good Parts

ISO BY DEFAULT

Page 41: JavaOne 2013: Java 8 - The Good Parts

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

Page 42: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: Java 8 - The Good Parts

APIENHANCEMENTS

Page 48: JavaOne 2013: Java 8 - The Good Parts

BETTER IO

Page 49: JavaOne 2013: 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: JavaOne 2013: Java 8 - The Good Parts

MAPS

Page 51: JavaOne 2013: 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: JavaOne 2013: Java 8 - The Good Parts

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

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

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

Page 53: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: Java 8 - The Good Parts

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

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

Page 56: JavaOne 2013: Java 8 - The Good Parts

LAMBDAS?

Page 57: JavaOne 2013: Java 8 - The Good Parts

LAMBDAS!(finally)

Page 58: JavaOne 2013: Java 8 - The Good Parts

LAMBDAS

Notable inspirations would be:

ScalaGroovyLisps

.NOT (!)

Page 59: JavaOne 2013: Java 8 - The Good Parts

() -> {}

LAMBDAS

Page 60: JavaOne 2013: Java 8 - The Good Parts

LAMBDAS

(Thing t) -> {}

Page 61: JavaOne 2013: Java 8 - The Good Parts

LAMBDAS

Page 62: JavaOne 2013: Java 8 - The Good Parts

LAMBDAS

(Thing t) -> {}

Page 63: JavaOne 2013: Java 8 - The Good Parts

LAMBDAS

(Thing t) -> {}

(Thing t, More m) -> {}

Page 64: JavaOne 2013: Java 8 - The Good Parts

LAMBDAS & TYPES

Page 65: JavaOne 2013: Java 8 - The Good Parts

LAMBDAS & TYPES

GetNum _ = (t) -> {42}

Page 66: JavaOne 2013: Java 8 - The Good Parts

LAMBDAS & TYPES

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

Page 67: JavaOne 2013: Java 8 - The Good Parts

LAMBDAS & TYPES

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

Page 68: JavaOne 2013: Java 8 - The Good Parts

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

TARGET TYPING

Page 69: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: Java 8 - The Good Parts

FUNCTIONAL INTERFACES

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

Page 77: JavaOne 2013: Java 8 - The Good Parts

FUNCTIONAL INTERFACES

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

Page 78: JavaOne 2013: 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: JavaOne 2013: Java 8 - The Good Parts

FUNCTIONAL INTERFACES

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

Page 80: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: Java 8 - The Good Parts

BEFORE LAMBDASin IntelliJ

Page 91: JavaOne 2013: Java 8 - The Good Parts

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

λ IN ACTION

Page 92: JavaOne 2013: 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: JavaOne 2013: Java 8 - The Good Parts

REMOVING BOILERPLATE

Page 94: JavaOne 2013: Java 8 - The Good Parts

STREAMS

Page 95: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: Java 8 - The Good Parts

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

compared to Scala

items map { _.getName }

Page 98: JavaOne 2013: Java 8 - The Good Parts

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

yay, we’re cool now!

compared to Scala

items map { _.getName }

Page 99: JavaOne 2013: 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: JavaOne 2013: Java 8 - The Good Parts

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

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

Page 101: JavaOne 2013: Java 8 - The Good Parts

PARALLELIZE?

Page 102: JavaOne 2013: Java 8 - The Good Parts

PARALLEL ITERATION

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

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

Page 103: JavaOne 2013: Java 8 - The Good Parts

STREAMS ARE LAZY!

Page 104: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: Java 8 - The Good Parts

METHOD HANDLESthink function pointers

Page 111: JavaOne 2013: Java 8 - The Good Parts

KEEPING REFERENCES

??? method = Person::getName

class Person { String getName();}

?

Page 112: JavaOne 2013: Java 8 - The Good Parts

KEEPING REFERENCES

Supplier<String> method = Person::getName

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

class Person { String getName();}

Page 113: JavaOne 2013: Java 8 - The Good Parts

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

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

Page 114: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: 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: JavaOne 2013: Java 8 - The Good Parts

THANK YOU!

Page 121: JavaOne 2013: Java 8 - The Good Parts

@ags313

Andrzej Grzesik Konrad Malawski

@ktosopl

TWEET PLEASE!