Read What's New in Java 8 - Leanpub
Read What's New in Java 8 - Leanpub
Read What's New in Java 8 - Leanpub
Sign In
Sign Up
An uno
$5.95
$11.99
1/5 3
4/25 /2016
Overview
2.
Lambda Expressions
2.1
Syntax
2.2
Scope
2.3
Method references
2.4
Functional Interfaces
2.5
Comparisons to Java 7
3.
Default Methods
3.1
3.2
Multiple Defaults
3.3
4.
Streams
4.1
What is a Stream?
4.2
Generating Streams
4.3
For Each
4.4
Map/Filter/Reduce
4.5
Parallel Array
4.6
Peek
4.7
Limit
4.8
Sort
4.9
2/5 3
4/25 /2016
4.10
4.11
Comparisons to Java 7
5.
Optional
6.
Nashorn
6.1
jjs
6.2
Scripting
6.3
ScriptEngine
6.4
Importing
6.5
Extending
6.6
Invocable
7.
7.1
New Classes
7.2
Creation
7.3
Enums
7.4
Clock
7.5
7.6
Temporal Adjusters
7.7
Instant
7.8
Time Zones
7.9
Backwards Compatibility
8.
9.
Miscellaneous
9.1
Base64
9.2
9.3
Repeating Annotations
3 /5 3
4/25 /2016
10.
10.1
Functions
10.2
Immutability
10.3
Concurrency
10.4
Tail-Call Optimization
11.
Conclusion
Backports
Preface
Like many Java developers, the first time I heard about lambda
expressions it piqued my interest. Also like many others, I was
disappointed when it was set back. However, it is better late than
never.
Java 8 is a giant step forward for the Java language. Writing this
book has forced me to learn a lot more about it. In Project Lambda,
Java gets a new closure syntax, method-references, and default
methods on interfaces. It manages to add many of the features of
functional languages without losing the clarity and simplicity Java
developers have come to expect.
Aside from Project Lambda, Java 8 also gets a new Date and T ime
API (JSR 310), the Nashorn JavaScript engine, and removes the
Permanent Generation from the HotSpot virtual machine, among
other changes.
I would like to acknowledge the following people for providing
valuable resources:
Brian Goetz State of the Lambda
h t t ps://lean pu b.com /wh at sn ewin java8 /read
4/5 3
4/25 /2016
1.
Overview
5 /5 3
4/25 /2016
2.
Lambda Expressions
2.1
Syntax
6/5 3
4/25 /2016
1 Arrays.sort(strArray,
2 (String s1, String s2) -> s2.length() - s1.length());
2.2
Scope
In the above, you can refer to the variable sql because it is only
assigned once. If you were to assign to it a second time, it would
cause a compilation error.
h t t ps://lean pu b.com /wh at sn ewin java8 /read
7/5 3
4/25 /2016
2.3
Method references
Whenever you want to filter a list of files, you can use a method
reference as in the following example (assuming you already
defined a method getFiles() that returns a Stream ):
1 Stream<File> pdfs = getFiles().filter(FileFilters::fileIsPdf);
2 Stream<File> txts = getFiles().filter(FileFilters::fileIsTxt);
3 Stream<File> rtfs = getFiles().filter(FileFilters::fileIsRtf);
8 /5 3
4/25 /2016
T he above reads the file Nio.java, calls trim() on every line, and then
prints out the lines.
Notice that System.out::println refers to the println method on an instance
of PrintStream .
2.4
Functional Interfaces
9/5 3
4/25 /2016
Github
See jdk8-lambda-samples for more examples.
2.5
Comparisons to Java 7
T o better
illustrate
the benefit of Lambda-expressions, here are
What's New
in Jav
a8
some examples of how code from Java 7 can be shortened in Java 8.
10/5 3
4/25 /2016
$5.95
Creating
an ActionListener
$11.99
MINIMUM
SUGGEST ED
1 // Java 7
2 ActionListener al = new ActionListener() {
3
@Override
4
public void actionPerformed(ActionEvent e) {
5
System.out.println(e.getActionCommand());
6
}
7 };
8 // Java 8
9 ActionListener al8 = e -> System.out.println(e.getActionCommand());
Sorting
For the sorting examples, assume you have the following Person
class:
1 public static class Person {
2
3
String firstName;
4
String lastName;
5
6
public String getFirstName() {
h t t ps://lean pu b.com /wh at sn ewin java8 /read
11/5 3
4/25 /2016
7
8
9
10
11
12
13 }
return firstName;
}
public String getLastName() {
return lastName;
}
Heres how you might sort this list in Java 7 by last-name and then
first-name:
1 Collections.sort(list, new Comparator<Person>() {
2
@Override
3
public int compare(Person p1, Person p2) {
4
int n = p1.getLastName().compareTo(p2.getLastName());
5
if (n == 0) {
6
return p1.getFirstName().compareTo(p2.getFirstName());
7
}
8
return n;
9
}
10 });
the byte-code.
3.
Default Methods
In order to add the stream method (or any others) to the core
h t t ps://lean pu b.com /wh at sn ewin java8 /read
12/5 3
4/25 /2016
3.1
13 /5 3
4/25 /2016
10 }
3.2
Multiple Defaults
In the above code, talk is overridden and calls Foos talk method. T his
is similar to the way you refer to a super class in pre-Java-8.
3.3
14/5 3
4/25 /2016
4.
Streams
4.1
What is a Stream?
4.2
Generating Streams
Streaming Collections
T he most obvious way to create a stream is from a Collection.
T he Collection interface has two default methods on it for creating
streams:
h t t ps://lean pu b.com /wh at sn ewin java8 /read
15 /5 3
4/25 /2016
Streaming Files
T he BufferedReader now has the lines() method which returns a Stream;
for example1:
1 try (FileReader fr = new FileReader("file");
2
BufferedReader br = new BufferedReader(fr)) {
3
br.lines().forEach(System.out::println);
4}
You can also read a file as a Stream using Files.lines(Path filePath); for
example:
1 try (Stream st = Files.lines(Paths.get("file"))) {
2
st.forEach(System.out::println);
3}
Note this populates lazily; it does not read the entire file when you
call it.
Files.lines(Path): Any IOException that is thrown while processing
the file (after the file is opened) will get wrapped in an
UncheckedIOException and thrown.
16/5 3
4/25 /2016
maximum depth.
T he above uses a very simple pattern, a comma, and splits the text
into a stream and prints it out. T his would produce the following
output:
1a
2b
3c
In nite Streams
Using the generate or iterate static methods on Stream, you can create
a Stream of values including never ending streams. For example,
you could call generate in the following way to create an infinite
supply of objects:
1 Stream.generate(() -> new Dragon());
17/5 3
4/25 /2016
However, the java.util.Random class does this for you with the following
new methods: ints(), longs(), and doubles(). Each of those methods is
overloaded with definitions similar to the following:
ints():
T his would print out 1234 continuously until you stop the
program.
T here are ways to limit an infinite stream which we will cover
later (filter and limit).
Ranges
T here are also new methods for creating ranges of numbers as
h t t ps://lean pu b.com /wh at sn ewin java8 /read
18 /5 3
4/25 /2016
Streams.
For example, the static method, range , on the IntStream interface:
1 IntStream.range(1, 11)
2
.forEach(System.out::println);
Streaming Anything
You can create a Stream from any number of elements or an array
using the two following methods:
1 Stream<Integer> s = Stream.of(1, 2, 3);
2 Stream<Object> s2 = Arrays.stream(array);
Stream.of
4.3
For Each
For the most part, this replaces the for loop. It is more concise,
and more object-oriented since you are delegating the
implementation of the actual loop.
19/5 3
4/25 /2016
4.4
Map/Filter/Reduce
T his could also be done in Java 7 with the dollar library (or similarly
with Guava or Functional-Java), but it would be much more verbose
as shown in the following:
1 PlayerPoints highestPlayer =
2 $(names).map(new Function<String, PlayerPoints>() {
h t t ps://lean pu b.com /wh at sn ewin java8 /read
20/5 3
4/25 /2016
3
4
5
6
7
8
9
10
11
12
4.5
Parallel Array
21/5 3
4/25 /2016
18
return student.gpa;
19
}
20
};
21 // create a fork-join-pool
22 ForkJoinPool fjPool = new ForkJoinPool();
23 ParallelArray<Student> students = new ParallelArray<>(fjPool, data
24 // find the best GPA:
25 double bestGpa = students.withFilter(isSenior)
26
.withMapping(selectGpa)
27
.max();
Groovy GPars
You can do something similar to this right now if you use
Groovy with the GPars library in the following way:
1 GParsPool.withPool {
2
// a map-reduce functional style (students is a Collection)
3
def bestGpa = students.parallel
4
.filter{ s -> s.graduationYear == Student.THIS_YEAR
h t t ps://lean pu b.com /wh at sn ewin java8 /read
22/5 3
4/25 /2016
5
6
7}
4.6
Peek
You can use any action you want, but you should not try to modify
elements; you should use map instead.
4.7
Limit
4.8
Sort
23 /5 3
4/25 /2016
Stream also has the sorted() method for sorting a stream. Like all
intermediate methods on Stream (such as map, filter, and peek), the
sorted()
Also, you should call sorted() after any calls to filter. For example, this
code prints out the first five Java file-names in the current directory:
1 Files.list(Paths.get("."))
2
.map(Path::getFileName) // still a path
3
.map(Path::toString) // convert to Strings
4
.filter(name -> name.endsWith(".java"))
5
.sorted() // sort them alphabetically
6
.limit(5) // first 5
7
.forEach(System.out::println);
24/5 3
4/25 /2016
4.9
Luckily, Java 8 comes with several Collectors built in. Import them
the following way:
1 import static java.util.stream.Collectors.*;
Simple Collectors
T he simplest collectors are things like toList() and toCollection():
1 // Accumulate names into a List
2 List<String> list = dragons.stream()
3
.map(Dragon::getName)
4
.collect(toList());
5
6 // Accumulate names into a TreeSet
7 Set<String> set = dragons.stream()
8
.map(Dragon::getName)
9
.collect(toCollection(TreeSet::new));
Joining
If youre familiar with Apache Commons StringUtil.join, the joining
collector is similar to it. It combines the stream using a given
delimiter. For example:
h t t ps://lean pu b.com /wh at sn ewin java8 /read
25 /5 3
4/25 /2016
T his would combine all of the names into one String separated by
commas.
Statistics
More complex collectors resolve to a single value. For example, you
can use an averaging Collector to get the average; for example:
1 System.out.println("\n----->Average line length:");
2 System.out.println(
3
Files.lines(Paths.get("Nio.java"))
4
.map(String::trim)
5
.filter(s -> !s.isEmpty())
6
.collect(averagingInt(String::length))
7
);
26/5 3
4/25 /2016
Equivalently, you can map your stream to a primitive type and then
call summaryStatistics(). For example:
1 IntSummaryStatistics stats = Files.lines(Paths.get("Nio.java"))
2
.map(String::trim)
3
.filter(s -> !s.isEmpty())
4
.mapToInt(String::length)
5
.summaryStatistics();
4.10
Parallel Grouping
T o execute grouping in parallel (if you dont care about
ordering) you should use the groupingByConcurrent method. T he
underlying stream should be unordered to allow grouping to
h t t ps://lean pu b.com /wh at sn ewin java8 /read
27/5 3
4/25 /2016
4.11
Comparisons to Java 7
Finding a maximum
1 // Java 7
2 double max = 0;
3
4 for (Double d : list) {
5
if (d > max) {
6
max = d;
7
}
8}
9 //Java 8
10 max = list.stream().reduce(0.0, Math::max);
11 // or
12 max = list.stream().mapToDouble(Number::doubleValue).max().getAsDouble
Calculating an average
1 double total = 0;
2 double ave = 0;
3 // Java 7
4 for (Double d : list) {
5
total += d;
6}
7 ave = total / ((double) list.size());
8 //Java 8
9 ave = list.stream().mapToDouble(Number::doubleValue).average().getAsDouble
28 /5 3
4/25 /2016
7
.forEach(System.out::println);
8 //or
9 Stream.iterate(1, i -> i+1).limit(10)
10
.forEach(System.out::println);
Joining Strings
1 // Java 7 using commons-util
2 List<String> names = new LinkedList<>();
3 for (Dragon dragon : dragons)
4
names.add(dragon.getName());
5 String names = StringUtils.join(names, ",");
6 // Java 8
7 String names = dragons.stream()
8
.map(Dragon::getName)
9
.collect(Collectors.joining(","));
5.
Optional
Java 8 comes with the Optional class in the java.util package for avoiding
null return values (and thus NullPointerException). It is very similar to
Google Guavas Optional, which is similar to Nat Pryces Maybe class
and Scalas Option class.
29/5 3
4/25 /2016
empty.
orElseGet(Supplier<T>) Calls on
the given
new Optional.
flatMap(Function<? super T,Optional<U>> mapper) Performs a
Stream Optional
T he new Stream interface has multiple methods which
return Optional (in case there are no values in the
Stream):
reduce(BinaryOperator<T> accumulator) Reduces the
h t t ps://lean pu b.com /wh at sn ewin java8 /read
3 0/5 3
4/25 /2016
maximum value.
min(Comparator<? super T> comparator) Finds the
minimum value.
6.
Nashorn
6.1
jjs
JDK 8 includes the command line tool jjs for running JavaScript.
You can run JavaScript files from the command line (assuming you
have Java 8s bin in your PATH):
1 $ jjs script.js
T his can be useful for running scripts; for example, lets say you
wanted to quickly find the sum of some numbers:
1 var data = [1, 3, 5, 7, 11]
2 var sum = data.reduce(function(x, y) {return x + y}, 0)
3 print(sum)
6.2
Scripting
3 1/5 3
4/25 /2016
You can also embed variables into strings and have them evaluate;
for example:
1 jjs> var date = new Date()
2 jjs> print("${date}")
6.3
ScriptEngine
T his way you can include and run any JavaScript. However, keep in
mind that the typical variables available to you in the browser
(window, document, etc.) are not available.
6.4
Importing
3 2/5 3
4/25 /2016
You can import and use Java classes and packages using the
JavaImporter.
For example, import java.util, the IO, and NIO file packages:
1 var imports = new JavaImporter(java.util, java.io, java.nio.file
2 with (imports) {
3
var paths = new LinkedList();
4
print(paths instanceof LinkedList); //true
5
paths.add(Paths.get("file1"));
6
paths.add(Paths.get("file2"));
7
paths.add(Paths.get("file3"));
8
print(paths) // [file1, file2, file3]
9}
We can use existing Java classes, but we can also create new ones.
6.5
Extending
You can extend Java classes and interfaces using the Java.type and
Java.extend functions. For
3 3 /5 3
4/25 /2016
10
executor.submit(task);
11 }
12 }
6.6
Invocable
7.
3 4/5 3
4/25 /2016
T ime.
7.1
New Classes
LocalTime
LocalDateTime
example:
3 5 /5 3
4/25 /2016
7.2
Creation
Creating new date and time objects is much easier and less errorprone in Java 8. Every type is immutable and has static factory
methods.
For example, creating a new LocalDate for March 15, 2014 is as
simple as:
1 LocalDate date = LocalDate.of(2014, 3, 15);
For more type-safety, you can use the new Month enum:
1 date = LocalDate.of(2014, Month.MARCH, 15);
You could also use any of the following methods (on LocalDate):
atTime(int hour, int minute)
atTime(int hour, int minute, int second)
atTime(int hour, int minute, int second, int nanoOfSecond)
Every class also has the now() method, which corresponds to the
instant (or date) it is called.
7.3
Enums
3 6/5 3
4/25 /2016
7.4
Clock
7.5
3 7/5 3
4/25 /2016
7.6
Temporal Adjusters
3 8 /5 3
4/25 /2016
lastDayOfMont()
next(DayOfWeek)
nextOrSame(DayOfWeek)
previous(DayOfWeek)
previousOrSame(DayOfWeek)
7.7
Instant
7.8
Time Zones
3 9/5 3
4/25 /2016
1 System.out.println(ZoneId.getAvailableZoneIds());
7.9
Backwards Compatibility
8.
Most allocations for the class metadata are now allocated out of
native memory. T his means that you wont have to set the
XX:PermSize options anymore (they dont exist).
T his also means that you will get a java.lang.OutOfMemoryError:
Metadata space error message instead of
java.lang.OutOfMemoryError: Permgen space when you run out of
memory.
T his is part of the convergence of the Oracle JRockit and HotSpot
JVMs.
9.
Miscellaneous
Java 8 has tons of new features that you might miss with all of the
focus on lambdas. Here are some of them:
h t t ps://lean pu b.com /wh at sn ewin java8 /read
40/5 3
4/25 /2016
java.util.Base64
Cryptography upgrades (lots)
JDBC 4.2
Repeatable Annotations
Annotations on types
9.1
Base64
9.2
41/5 3
4/25 /2016
9.3
Repeating Annotations
42/5 3
4/25 /2016
10.
10.1
Functions
43 /5 3
4/25 /2016
functional interfaces.
T he Function interface (and related interfaces IntFunction,
DoubleFunction, LongFunction, BiFunction, etc.) represents the
compromise made by Java 8 in elevating functions to objects. T his
interface allows functions to be passed as arguments, stored as
variables, and be returned by methods.
T he Function interface has the following default methods:
andThen(Function):
this function to its input, and then applies the given function to
the result.
compose(Function):
applies the given function to its input, and then this function).
identity():
argument.
You can use these methods to create a chain for creating a function;
for example:
1 Function<Integer,String> f = Function.<Integer>identity()
2
.andThen(i -> 2*i).andThen(i -> "str" + i);
44/5 3
4/25 /2016
Tuples
If you need a functional interface for a method with more than two
parameters (eg. T riFunction) you need to make it yourself or use a
library. Another way to handle this issue is to use a data structure
called a T uple.
A T uple is a typed data structure for holding a number of elements.
Some languages, such as Scala, have built-in support for T uples.
T uples are useful whenever you are handling multiple related
values, but dont want all of the overhead of creating a new class.
Heres a very simple example of implementing a T uple with two
elements:
1 public class Tuple2<A, B> {
2
public final A _1;
3
public final B _2;
4
5
public Tuple2(A a, B b) {
6
this._1 = a;
7
this._2 = b;
8
}
9
10
@Override
11
public A get_1() {
12
return _1;
13
}
14
15
@Override
16
public B get_2() {
17
return _2;
18
}
19 }
45 /5 3
4/25 /2016
10.2
Immutability
You may think you are being clever, but this kind of thing can cause
problems. Instead, you should do something like the following:
1 list.stream().filter(Dragon::isGreen).count();
10.3
Concurrency
46/5 3
4/25 /2016
47/5 3
4/25 /2016
calculation).
However, this could be simplified using the parallelStream() default
method (since only one type of calculation is going on) in the
following way:
1 public Dragon closestDragon(Location location) {
2
return dragons.parallelStream()
3
.map(dragon -> dragon.distance(location))
4
.reduce(DistancePair.worstMatch(), DragonDistance::closest
5
.getDragon();
6}
10.4
Tail-Call Optimization
48 /5 3
4/25 /2016
9
10
11
12
13
14
15
16
17
18
19
20
default T result() {
throw new UnsupportedOperationException("Not done yet."
}
default T invoke() {
return Stream.iterate(this, Tail::apply)
.filter(Tail::isDone)
.findFirst()
.get()
.result();
}
T he Tail interface has three default methods and one abstractmethod (apply). T he invoke() method contains the meat of the tailcall optimization:
It takes advantage of Streams iterate method to create an infinite
Stream which will continuously call Tails apply method.
Then it uses filter and findFirst to stop the Stream when isDone()
returns true.
Finally, it returns the result.
With the Tail interface you can mimic tail-call recursion quite easily
h t t ps://lean pu b.com /wh at sn ewin java8 /read
49/5 3
4/25 /2016
Using this method, you can make extremely fast programs while
still maintaining the functional style.
Of course the JVM does a lot optimization by itself, so this may not
always be the best course. However, it is something to keep in mind.
11.
Conclusion
5 0/5 3
4/25 /2016
Lambda expressions
Method references
Default Methods (Defender methods)
A new Stream API.
Optional
A new Date/Time API.
Nashorn, the new JavaScript engine
Removal of the Permanent Generation
Backports
If for some reason you cant immediately upgrade to Java 8, there
are some ways to backport some Java 8 features to previous
versions.
For each of the following features, here is the backport or similar
library:
Lambdas Retrolambda
Lazily Evaluated Sequences totallylazy
Optional guava
Date/Time ThreeTen
Nashorn nashorn-backport
5 1/5 3
4/25 /2016
About Leanpub
What Is Leanpub?
Blog
Team
Buzz
Testimonials
Podcast
Press
Contact Us
Readers
In-Progress & Serial Publishing
Ebook Formats With No DRM
Variable Pricing
100% Happiness Guarantee
Interacting With Authors
The Leanpub App
Kindle Support
Reader FAQ
Reader Help
Authors
Leanpub For Authors
'How To' Introduction
Writing With Leanpub
Writing In Word
Publishing With Leanpub
Royalties and Payments
Leanpub Book Pricing
Uploading A Book
Packaging Books With Videos
The Lean Publishing Manifesto
Author Manual
Author FAQ
Author Help
Books
Agile
Data Science
Computer Programming
Fiction
h t t ps://lean pu b.com /wh at sn ewin java8 /read
5 2/5 3
4/25 /2016
Non-Fiction
More...
More
Leanpub for Causes
Publishers
Friends of Leanpub
Terms of Service
Copyright Take Down Policy
Privacy Policy
5 3 /5 3