java 8 dos and don'ts - javabin oslo may 2015

Post on 08-Aug-2015

339 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Java 8 and .

1

javaBin Oslo – 12.05.2015

Fredrik Vraalsen

fredriv vraalsen@iterate.no

2

Java 8 – what’s new?Lambdas

Method handles

Extension methods

Streams

Optional3

Java 8 – what’s new?Lambdas (anonymous functions)

Method handles

Extension methods

Streams

Optional4

5

Java 7 vs 8Collections.sort(people, new Comparator<Person>() { public int compare(Person x, Person y) { return x.getName().compareTo(y.getName()); } });

6

Java 7 vs 8Collections.sort(people, new Comparator<Person>() { public int compare(Person x, Person y) { return x.getName().compareTo(y.getName()); } });

vs

sort(people, (x, y) -> x.getName().compareTo(y.getName()));

7

Java 7 vs 8Collections.sort(people, new Comparator<Person>() { public int compare(Person x, Person y) { return x.getName().compareTo(y.getName()); } });

vs

sort(people, comparing(person -> person.getName()));

8

Java 7 vs 8Collections.sort(people, new Comparator<Person>() { public int compare(Person x, Person y) { return x.getName().compareTo(y.getName()); } });

vs

sort(people, comparing(Person::getName));

9

Java 7 vs 8Collections.sort(people, new Comparator<Person>() { public int compare(Person x, Person y) { return x.getName().compareTo(y.getName()); } });

vs

people.sort(comparing(Person::getName));

10

Streams

© Fredrik Vraalsen 2008

Old fashioned imperative

12

List<RoadData> filtered = new ArrayList<>();int count = 0; for (Iterator<RoadData> i = roadData.iterator(); i.hasNext() && count < 10; ) { RoadData data = i.next(); if (nameQuery.matches(data.getName())) { filtered.add(data); count++; }}

Streams

13

roadData.stream() .filter(data -> nameQuery.matches(data.getName())) .limit(10) .collect(toList());

Streams – pipelines

14

roadData.stream() .filter(data -> nameQuery.matches(data.getName())) .limit(10) .collect(toList());

cat roadData.txt | grep … | head > output.txt

Learn you a Stream API

15

Map<String, List<Article>> articlesByCategory =

Learn you a Stream API

16

Map<String, List<Article>> articlesByCategory = articleTransports.stream()

Learn you a Stream API

17

Map<String, List<Article>> articlesByCategory = articleTransports.stream() .map(transport -> convertToArticle(transport))

Learn you a Stream API

18

Map<String, List<Article>> articlesByCategory = articleTransports.stream() .map(transport -> convertToArticle(transport)) .collect(groupingBy(article -> article.getCategory()));

Learn you a Stream API

19

Method handles

20

Map<String, List<Article>> articlesByCategory = articleTransports.stream() .map(transport -> convertToArticle(transport)) .collect(groupingBy(article -> article.getCategory()));

Map<String, List<Article>> articlesByCategory = articleTransports.stream() .map(this::convertToArticle) .collect(groupingBy(article -> article.getCategory()));

Method handles

21

Method handles

22

Map<String, List<Article>> articlesByCategory = articleTransports.stream() .map(this::convertToArticle) .collect(groupingBy(Article::getCategory));

Naming, caching, counting

23

Map<String, List<Article>> articlesByCategory = articleTransports.stream() .map(this::convertToArticle) .collect(groupingBy(Article::getCategory));

Naming, caching, counting

24

Map<String, List<Article>> articlesByCategory = articleTransports.stream() .map(this::transportToArticle) .collect(groupingBy(Article::category));

Extract functions

25

Map<String, List<Article>> articlesByCategory = articleTransports.stream() .map(transportToArticle) .collect(groupingBy(Article::category));

Function<ArticleTransport, Article> transportToArticle = transport -> convertToArticle(transport);

Lambdas everywhere!!!1!links.stream() .map(link -> link.build()) .forEach(abderaElement::addLink);

26

Old school ifs and forslinks.stream() .map(link -> link.build()) .forEach(abderaElement::addLink);

for (LinkBuilder lb : links) { abderaElement.addLink(lb.build()); }

27

Parsing nested JSON "suggest": { "tag_suggest": [ { "length": 5, "offset": 0, "options": [ { "freq": 25, "score": 0.8, "text": "fakta" } ], "text": "fanta" } ] } 28

Lambdas everywhere!!!1!List<String> terms = new ArrayList<>();

suggestions.getAsJsonObject().getAsJsonArray(“tag_suggest”) .forEach(tag -> tag.getAsJsonObject().getAsJsonArray("options") .forEach(option -> terms .add(option.getAsJsonObject().getAsJsonPrimitive("text") .getAsString())));

29

Old school ifs and forsList<String> terms = new ArrayList<>();

for (JsonElement tag : suggestions.getAsJsonObject().getAsJsonArray("tag_suggest")) { for (JsonElement option : tag.getAsJsonObject().getAsJsonArray("options")) { terms.add(option.getAsJsonObject().getAsJsonPrimitive("text").getAsString()); } }

30

Old school ifs and forsList<String> terms = new ArrayList<>();

for (JsonElement tag : getAll("tag_suggest", suggestions)) { for (JsonElement option : getAll("options", tag)) { terms.add(getString("text", option)); } }

31

List<String> terms = getAll("tag_suggest", suggestions).stream() .flatMap(tag -> getAll("options", tag).stream()) .map(option -> getString("text", option)) .collect(Collectors.toList());

32

Lambdas everywhere!!!1!

Readability ≫ Style / LOC

Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live.

http://c2.com/cgi/wiki?CodeForTheMaintainer

OH NOES

NullPointerException!!?!© Fredrik Vraalsen 201

Optional<T>Wrapper object

Make explicit if a value is present or absent (empty)

35

Optional examplepublic Optional<Image> getImage(Article article)

---

36

Optional examplepublic Optional<Image> getImage(Article article)

---

Optional<Image> image = getImage(article);

37

Check presencepublic Optional<Image> getImage(Article article)

---

Optional<Image> image = getImage(article);if (image.isPresent()) { doSomething(image.get());}

38

Check presencepublic Optional<Image> getImage(Article article)

---

Optional<Image> image = getImage(article);image.ifPresent(img -> doSomething(img));

39

Check presencepublic Optional<Image> getImage(Article article)

---

getImage(article).ifPresent(image -> doSomething(image));

40

Default / fallback valuepublic Optional<Image> getImage(Article article)

---

Image image = getImage(article).orElse(defaultImage);

41

Optional in / Optional outpublic Optional<String> getCaption(Optional<Image> image)

---

Optional<Image> image = getImage(article);Optional<String> caption = getCaption(image);

42

Optional in / Optional outpublic String getCaption(Image image)

---

Optional<Image> image = getImage(article);Optional<String> caption = ???

43

Reaching into the void …public String getCaption(Image image)

---

Optional<Image> image = getImage(article);Optional<String> caption = image.map(img -> getCaption(img));

44

Reaching into the void …public String getCaption(Image image)

---

Optional<String> caption = getImage(article) .map(img -> getCaption(image));

45

Bye bye NullPointerException?Marker – this may not return/contain value

Public APIs

Not a general solution to NPEs

46

Optional + Streams = true?

47

Optional + Streams = true?

48

myStream.map(v -> functionReturningOptional(v))

Optional + Streams = true?

49

myStream.map(v -> functionReturningOptional(v))

Stream<Optional<T>>

Optional + Streams = true?

50

myStream.map(v -> functionReturningOptional(v))

Stream<Optional<T>> ⇒ Stream<T> ???

Guava Optional

51

Iterable<T> presentInstances(Iterable<Optional<T>> optionals)

Optional + Streams = true?

52

public Optional<Image> getImage(Article article)

---

List<Image> images = articles.stream() // Stream<Article>

Optional + Streams = true?

53

public Optional<Image> getImage(Article article)

---

List<Image> images = articles.stream() // Stream<Article> .map(article -> getImage(article)) // Stream<Optional<Image>>

Optional + Streams = true?

54

public Optional<Image> getImage(Article article)

---

List<Image> images = articles.stream() // Stream<Article> .map(article -> getImage(article)) // Stream<Optional<Image>> .filter(Optional::ifPresent) .map(Optional::get) // Stream<Image>

Optional + Streams = true?

55

public Optional<Image> getImage(Article article)

---

List<Image> images = articles.stream() // Stream<Article> .map(article -> getImage(article)) // Stream<Optional<Image>> .filter(Optional::ifPresent) .map(Optional::get) // Stream<Image> .collect(toList());

flatMap to the rescue!flatMap = map + flatten

Stream<Stream<T>> ⇒ Stream<T>

56

flatMap to the rescue!flatMap = map + flatten

Stream<Optional<T>> ⇒ Stream<T> ???

57

flatMap to the rescue!Easy to create helper functions

Stream<T> toStream(Optional<T> optValue)

58

http://stackoverflow.com/questions/22725537/using-java-8s-optional-with-streamflatmap

Optional + Streams = true?

59

public Optional<Image> getImage(Article article)

---

List<Image> images = articles.stream() // Stream<Article> .map(article -> getImage(article)) // Stream<Optional<Image>> .filter(Optional::ifPresent) .map(Optional::get) // Stream<Image> .collect(toList());

Optional + Streams = true

60

public Optional<Image> getImage(Article article)

---

List<Image> images = articles.stream() // Stream<Article> .flatMap(article -> toStream(getImage(article))) // Stream<Image> .collect(toList());

Optional + Streams = true

61

public Optional<Image> getImage(Article article)

---

List<Image> images = articles.stream() // Stream<Article> .flatMap(article -> getImage(article).stream()) // Stream<Image> .collect(toList());

Java 9

https://bugs.openjdk.java.net/browse/JDK-8050820

Take one stream and pass it around…

62

public Stream<Image> getImage(Article article)

---

List<Image> images = articles.stream() // Stream<Article> .flatMap(article -> getImage(article)) // Stream<Image> .collect(toList());

No method handle for you!

63

private Article elementToArticle(Map contentById, Element el)

---

List<Article> articles = elements.stream() .map(el -> elementToArticle(contentById, el)) .collect(toList())

64

http://en.wikipedia.org/wiki/Malabar_matthi_curry#/media/File:Meen_curry_2_(cropped).JPG

Yummy currying!!

65

Mapper mapper = new Mapper(contentById);

---

List<Article> articles = elements.stream() .map(el -> mapper.elementToArticle(el)) .collect(toList())

Yummy currying!!

66

Mapper mapper = new Mapper(contentById);

---

List<Article> articles = elements.stream() .map(mapper::elementToArticle) .collect(toList())

Performance

© Fredrik Vraalsen 2012

Streams – performanceList<Article> frontpageArticles = frontpage.getArticleIds().stream() .map(id -> fetchArticle(id)) .collect(toList());

68

This one goes to 11!List<Article> frontpageArticles = frontpage.getArticleIds().parallelStream() .map(id -> fetchArticle(id)) .collect(toList());

69

StarvationCommon F/J thread pool

Workarounds?

Execute within explicit F/J pool

Use CompletableFuture

70

CompletableFutureChaining of async futures and actions

Waiting for all or any future(s)

Explicitly complete (like Promise)

Control of executor service

71

http://blog.krecan.net/2014/03/18/how-to-specify-thread-pool-for-java-8-parallel-streams/http://www.nurkiewicz.com/2013/05/java-8-completablefuture-in-action.html

To parallelStream or not to …Batch?

parallelStream FTW!

Interactive? Concurrency?

CompletableFuture FTW!72

Taking the happy path!Try<RestResponse<ResolvedUri>> resolveURI(URI uri)

---

public ResolvedSectionUri resolveSectionUri(String uri) { return client.resolveURI(uri))

??? Try<RestResponse<ResolvedUri>>

}

73

Taking the happy path!Try<RestResponse<ResolvedUri>> resolveURI(URI uri)

---

public ResolvedSectionUri resolveSectionUri(String uri) { return client.resolveURI(uri)) .map(response -> response.getEntity())

??? Try<Optional<ResolvedUri>>

}

74

Taking the happy path!Try<RestResponse<ResolvedUri>> resolveURI(URI uri)

---

public ResolvedSectionUri resolveSectionUri(String uri) { return client.resolveURI(uri)) .map(response -> response.getEntity().get())

??? Try<ResolvedUri>

}

75

Taking the happy path!Try<RestResponse<ResolvedUri>> resolveURI(URI uri)

---

public ResolvedSectionUri resolveSectionUri(String uri) { return client.resolveURI(uri)) .map(response -> (ResolvedSectionUri) response.getEntity().get())

??? Try<ResolvedSectionUri>

}

76

Taking the happy path!Try<RestResponse<ResolvedUri>> resolveURI(URI uri)

---

public ResolvedSectionUri resolveSectionUri(String uri) { return client.resolveURI(uri)) .map(response -> (ResolvedSectionUri) response.getEntity().get()) .orElse(null);

}

77

Taking the happy path!Try<RestResponse<ResolvedUri>> resolveURI(URI uri)

---

public ResolvedSectionUri resolveSectionUri(String uri) { return client.resolveURI(uri)) .map(response -> (ResolvedSectionUri) response.getEntity().get()) .orElseGet(() -> { log.warn("Cannot resolve section from URI: {}", uri); return null; });}

78

https://github.com/lambdista/try

More cool stuff in Java 8String join

Collection removeIf (≈ filter)

Map getOrDefault, putIfAbsent, replace, forEach, etc.

java.util.Optional

java.util.stream.Collectors

count, sum, average, min, max, groupingBy, etc.

java.nio.file.Files lines79

Functional programmingSimpler code

More robust

Better performance

Higher levelDeclarative

Less verbose

Less bugs?

81

List<RoadData> filtered = new ArrayList<>();int count = 0; for (Iterator<RoadData> i = roadData.iterator(); i.hasNext() && count < 10; ) { RoadData data = i.next(); if (nameQuery.matches(data.getName())) { filtered.add(data); count++; } }

roadData.stream() .filter(data -> nameQuery.matches(data.getName())) .limit(10) .collect(toList());

vs.

Pure functions

82

Data In Data Out

Transformation

No external interactions

Functional core

83

————- —— ——— —- — —- —-—————————— —- — —- ——————— — — — ——-——- —- — —————- ——— ——————- —— ———— - —-———- — —- — -

Pure functionsI/O I/O

Building blocks

© Fredrik Vraalsen 201

What’s missing?© Fredrik Vraalsen 2012

What’s missing?Immutability

Value types

Data structures (lists, maps, etc.)

Concurrency

86

What’s the big deal?Functional programming is all about values!

And transformations (functions) computing new values

Parallellism vs. Concurrency

Robustness

Testability

87

Some help to be foundImmutable collections

Google Guava, FunctionalJava, clj-ds

Concurrency mechanisms

Akka (Actors, STM)

88

github.com/krukow/clj-dsPersistentVector<Person> people = Persistents.vector( new Person("Fredrik", 39), new Person("Hedda", 3));

89

github.com/krukow/clj-dsPersistentVector<Person> people = Persistents.vector( new Person("Fredrik", 39), new Person("Hedda", 3));

PersistentVector<Person> morePeople = people.plus(new Person("Johannes", 5));

90

github.com/krukow/clj-dsPersistentVector<Person> people = Persistents.vector( new Person("Fredrik", 39), new Person("Hedda", 3));

PersistentVector<Person> morePeople = people.plus(new Person("Johannes", 5));

morePeople.stream() .forEach(p -> System.out.println(p.getName()));

91

Why use X instead?Java 8 ready for enterprise dev?

JBoss AS, WebSphere – Nope

WildFly, GlassFish, WebLogic, Jetty, Tomcat – OK?

Important things are still missing from Java 8

Clojure and Scala available on JDK 6+!

92

Questions?

© Fredrik Vraalsen 2012

fredriv

vraalsen@iterate.no

top related