Java 8 Streams
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

Java 8 Streams

  • 3,040 views
Uploaded on

This is a brief introduction to "Java 8 Streams" featuring: ...

This is a brief introduction to "Java 8 Streams" featuring:
* Bulk Operations
* Lambda Expressions
* Method References
* Functional Operations
* Collectors
* ...

Accompanying source code and examples can be found on https://github.com/bkimminich/java8-streams

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
3,040
On Slideshare
2,457
From Embeds
583
Number of Embeds
7

Actions

Shares
Downloads
40
Comments
0
Likes
3

Embeds 583

http://kimminich.de 363
http://kimminich.wordpress.com 147
http://www.kimminich.de 28
http://www.techgig.com 24
https://kimminich.wordpress.com 9
http://www.linkedin.com 6
http://bkimminich.tumblr.com 6

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Java 8 Streams Björn Kimminich https://twitter.com/bkimminich https://linkedin.com/in/bkimminich https://google.com/+BjörnKimminich http://slideshare.net/BjrnKimminich/ J8S 1.2.1 (24.01.2014)
  • 2. Agenda Introduction • • • • Java 8 Streams Lambdas Method References Stream Operations • • • • Intermediate vs. Terminal Stateless vs. Stateful Short-Circuiting Collectors
  • 3. Java 8
  • 4. Java™ SE 8 Release Contents JSR 308: Annotations on Java Types JSR 310: Date and Time API JSR 335: Lambda Expressions closures JEP 107: Bulk Data Operations for Collections for-each filter map reduce http://www.jcp.org/en/jsr/detail?id=337 http://openjdk.java.net/jeps/107
  • 5. Streams
  • 6. Streams interface java.util.stream.Stream<T> forEach() filter() map() reduce() … java.util.Collection<T> Stream<T> stream() Stream<T> parallelStream()
  • 7. Creating and using a Stream List<Book> myBooks = …; Stream<Book> books = myBooks.stream(); Stream<Book> goodBooks = books.filter(b -> b.getStarRating() > 3); goodBooks.forEach(b -> System.out.println(b.toString()));
  • 8. Properties of Streams Streams do not store elements… …they are a view on top of a data structure Operations provided by Streams... …are applied to the underlying data source elements Stream Operations can take as a parameter… …Lambda expressions …Method references Manipulating the underlying data source... …will yield a ConcurrentModificationException
  • 9. Lambdas
  • 10. What are Lambda Expressions? Java‘s version of Closures Allow to create (sort of) First Class Functions Can be passed as a parameter Can be a return value Can be stored in a variable Target type is inferred from context Why „sort of“? Because Java doesn‘t have a real function type! Java converts Lambdas into Functional Interfaces
  • 11. Functional Interface Functional Interface = Interface w/ 1 Method Names of Interface and Method are irrelevant Default: java.util.function.Consumer<T> public interface Stream<T> { void forEach(Consumer<? super T> consumer); } public interface Consumer<T> {void accept(T t);} Consumer<Book> reduceRankForBadAuthors = (Book b) -> { if (b.getStarRating() < 2) b.getAuthor().addRank(-1); }; books.forEach(reduceRankForBadAuthors); books.forEach(b -> b.setEstimatedReadingTime(90*b.getPages()));
  • 12. Lambda Syntax /* argument list */ (int x, int y) -> { return x*y; } (x, y) -> { return x*y; } x -> { return x*2; } () -> { System.out.println("Do you think this will work?"); } /* single expression */ b -> { b.getMissingPages() > threshold ? b.setCondition(BAD) : b.setCondition(GOOD) } /* list of statements */ b -> { Condition c = computeCondition(b.getMissingPages()); b.setCondition(c); }
  • 13. Method References
  • 14. Method References books.forEach(b -> b.fixSpellingErrors()); books.forEach(Book::fixSpellingErrors); // instance method books.forEach(b -> BookStore.generateISBN(b)); books.forEach(BookStore::generateISBN); // static method books.forEach(b -> System.out.println(b.toString())); books.forEach(System.out::println); // expression Stream<ISBN> isbns1 = books.map(b -> new ISBN(b)); Stream<ISBN> isbns2 = books.map(ISBN::new); // constructor
  • 15. Intermediate vs. Terminal Stream Operations
  • 16. Intermediate vs. Terminal Intermediate: Output is another Stream filter() map() … Terminal: Do something else with the Stream forEach() reduce() … double totalPrice = books.mapToDouble(Book::getPrice) .reduce(0.0, (p1, p2) -> p1+p2);
  • 17. Stream Evaluation Intermediate Streams are not evaluated… …until a Terminal Operation is invoked on them Intermediate = Lazy Terminal = Eager (Consuming) This allows Java to… …do some code optimization during compilation …avoid buffering intermediate Streams …handle parallel Streams more easily
  • 18. Terminal = Consuming Operations books.forEach(b -> System.out.println("Book: " + b.getTitle())); double totalPrice = books.reduce(0.0, (b1, b2) -> b1.getPrice() + b2.getPrice()); Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed Intermediate Operations can be chained Only one Terminal Operation can be invoked Best avoid reference variables to Streams entirely by using Fluent Programming Construction  (Intermediate)*  Terminal;
  • 19. Stateless vs. Stateful Stream Operations
  • 20. Stateless Intermediate Operations Operation need nothing other than the current Stream element to perform its work Examples map()  Maps element to something else filter()  Apply predicate and keep or drop element List<Book> myBooks = ...; double impairments = myBooks.stream() .filter(b -> b.getCondition().equals(BAD)) .mapToDouble(Book::getPrice) .reduce(0.0, (p1, p2) -> p1 + p2);
  • 21. Stateful Intermediate Operations Operations that require not only the current stream element but also additional state distinct()  Element goes to next stage if it appears the first time sorted()  Sort elements into natural order sorted(Comparator)  Sort according to provided Comparator substream(long)  Discard elements up to provided offset substream(long, long)  Keep only elements in between offsets limit(long)  Discard any elements after the provided max. size myBooks.stream().map(Book::getAuthor).distinct().forEach(System.out::println);
  • 22. Short-Circuiting Stream Operations
  • 23. Short-Circuiting Operations Processing might stop before the last element of the Stream is reached Intermediate limit(long) substream(long, long) Terminal Author rp = new Author("Rosamunde Pilcher"); anyMatch(Predicate) allMatch(Predicate) boolean phew = myBooks.stream() .map(Book::getAuthor) noneMatch(Predicate) .noneMatch(isEqual(rp)); findFirst() System.out.println("Am I safe? " + phew); findAny()
  • 24. Collectors
  • 25. Collectors <R> R collect(Collector<? super T, A, R> col) Collect the elements of a Stream into some other data structure Powerful and complex tool Collector is not so easy to implement, but… …luckily there are lots of factory methods for everyday use in java.util.stream.Collectors toList() toSet() toCollection(Supplier) toMap(Function, Function) …
  • 26. Collector Examples List<Author> authors = myBooks.stream() .map(Book::getAuthor) .collect(Collectors.toList()); double averagePages = myBooks.stream() .collect(Collectors.averagingInt(Book::getPages));
  • 27. Joining Collector Used for concatenation of CharSequences Internally implemented using StringBuilder A lot more efficient than a Map-Reduce with intermediately concatenated Strings // not efficient due to recursive String concatenation. And ugly. String titleList = myBooks.stream().map(Book::getTitle).reduce("", (t1, t2) -> t1+t2); // Still inefficient. Still ugly (initial line break) titleList = myBooks.stream().map(Book::getTitle).reduce("", (t1, t2) -> t1+"n"+t2); // more efficient thanks to StringBuilder. Pretty printed. titleList = myBooks.stream().map(Book::getTitle).collect(Collectors.joining("n"));
  • 28. Thank you… …for your attention! All code examples: https://github.com/bkimminich/java8-streams