JAVA 8
NEW FEATURES
or the ones you might actually use
Sharon Rozinsky
18/3/2014Release Date
Java 8 adoption is running
six months ahead of the
original predictions
http://www.baeldung.com/java-8-adoption-march-2016
1.
Lambda Expressions
Encapsulate a functionality and pass it as an argument
Replace the cumbersome syntax of anonymous functions
Let’s try an example - write a code to search a list of
people by a certain criteria
Attempt
#
1
Attempt
#
2
Attempt
#
3
public static void printPeopleWithinAgeRange(
List<Person> people, int low, int high) {
for (Person p : people) {
if (low <= p.getAge() && p.getAge() < high) {
p.printPerson();
}
}
}
But what if the search criteria changes?
Attempt
#
1
Attempt
#
2
Attempt
#
3
public static void printPeople(List<Person> people,
CheckPerson tester) {
for (Person p : people) {
if (tester.test(p)) {
p.printPerson();
}
}
}
printPeople(
people,
new CheckPerson() {
public boolean test(Person p) {
return p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25;
}
}
);
Okay - let’s try it with lambda’s
Attempt
#
1
Attempt
#
2
Attempt
#
3
printPeople(
people,
(Person p) -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
);
CheckPerson must be a functional interface!
Syntax Rules
Basic
(p1, p2, …) -> {statements}
Syntax Rules
Evaluate And Return
p -> p.getAge() > 25
Syntax Rules
Multiple Statements
p -> {
int x = 25;
return p > x;
}
Method References
Use lambda expressions to reference methods.
There are 4 kinds of method references:
Method References
Arrays.sort(stringArray, String::compareToIgnoreCase);
==
Arrays.sort(stringArray, (String a, String b) ->
a.compareToIgnoreCase(b));
2.
Functional Interfaces
An interface with only one abstract method.
(possible to have more non abstract methods
using default).
Not a new concept:
Runnable, Callable, Comparator etc...
We saw that we can create instances of functional
interfaces using lambdas.
*Remember the CheckPerson interface from the first example.
@FunctionalInterface
(not a must if demands are met = only 1 method)
The java.util.function package contains many built in functional
interfaces:
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
Predicate<Person> canDrive = p -> p.getAge() > 16;
The java.util.function package contains many built in functional
interfaces:
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
Function<String, Integer> intToString = x ->
Integer.valueOf(x);
3.
Default Methods
Add functionality to interfaces without breaking
backward compatibility.
New keyword: default
Enables method implementation in interfaces
Side effect of Oracle’s extensions to the collection
interfaces.
Example
public interface Person {
void goSomewhere(Location location);
}
public Class NicePerson implements Person{
public void goSomewhere(Location location) {
…
}
}
Now Let’s add a method to the Person interface -
void saySomething (String whatToSay)
public interface Person {
void goSomewhere(Location location);
default void saySomething (String whatToSay) {
…
Sysout.println(whatToSay);
}
}
Adding a default method to an interface requires
no additions to the implementing classes.
Like any other method in the interface default
methods are implicitly public
Extending an interface with a default method:
Default method is not mentioned - extended
interface gets the default method.
Extending an interface with a default method:
Redeclaring the default method - method
becomes abstract (and implementing class has to
implement it).
Extending an interface with a default method:
Redefine the default method - override the
method functionality.
Any Famous Problem You Can Think Of?
Diamond Problem
interface InterfaceA {
default public void sayHi() {
System.out.println("Hi from InterfaceA");
}
}
interface InterfaceB {
default public void sayHi() {
System.out.println("Hi from InterfaceB");
}
}
public class MyClass implements InterfaceA, InterfaceB {
public static void main(String[] args) {
...
}
}
interface InterfaceA {
default public void sayHi() {
System.out.println("Hi from InterfaceA");
}
}
interface InterfaceB {
default public void sayHi() {
System.out.println("Hi from InterfaceB");
}
}
public class MyClass implements InterfaceA, InterfaceB {
public static void main(String[] args) {
...
}
}
Compilation
Error!
Solution:
- Provide implementation to sayHi in MyClass
- Can use: InterfaceA.super.sayHi()
Default methods are never final
Default methods cannot be synchronized
Default methods are always public
There are no fields in an interface - hard to maintain a state
For most cases - classes define what an object is while an interface
defines what an object can do
Interfaces vs. Abstract Classes
4.
Streams
A new Java API that helps processing data and
collections in a declarative way.
Formal definition: “A sequence of elements
supporting sequential and parallel aggregate
operations.”
The Pipeline Approach
Java streams use a pipeline approach to perform the different tasks
needed to process a given collection.
A pipeline is composed of the following:
Source - any structure that holds data: array,
collection, I/O channel, generator functions, etc…
A pipeline is composed of the following:
Intermediate operations - 0 or more operations
that produce a new stream. The basic examples
for this are the Stream() and Filter() operations.
A pipeline is composed of the following:
Terminal operation - an operation that returns a
non stream value e.g. primitives, collections or no
value at all.
Example
double average = people
.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.mapToInt(Person::getAge)
.average()
.getAsDouble();
Produce a stream from the given collection
double average = people
.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.mapToInt(Person::getAge)
.average()
.getAsDouble();
Filter on a predicate - produces another
stream
double average = people
.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.mapToInt(Person::getAge)
.average()
.getAsDouble();
Map only the age of each person - return a
stream of type IntStream
double average = people
.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.mapToInt(Person::getAge)
.average()
.getAsDouble();
Perform average on all values - returns an
OptionalDouble
double average = people
.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.mapToInt(Person::getAge)
.average()
.getAsDouble();
Return the final value
int numberOfMales = 0;
int totalAge = 0;
foreach(person p : people){
if(p.getGender() == Person.Sex.MALE){
numberOfMales++;
totalAge += p.getAge();
}
}
if(numberOfMales > 0){
return totalAge / numberOfMales;
}
Old School Way:
Reduce
The average() operation from the previous example is one of
many reduction methods (the terminal operations)
The Java 8 API provides handy reduction operations but also a
more generic method to perform reduction by yourself
double agesSum = people
.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.mapToInt(Person::getAge)
.reduce(0, (a,b) -> a + b)
Identity - an initial and
also default value if the
stream is empty.
Accumulator - an
associative function
reduce also has a 3 parameter version that
accepts an identity, a mapper which replaces the
mapToInt in this case and a combiner function
that serves as an accumulator
Collect
The reduce method creates a new value for every element that it
processes.
The collect method modifies an existing value.
Think about creating the average ages in the last example (Yap it’s hard
with reduce…).
Let’s try it with collect:
Before we begin:
IntCosumer - a built in functional interface that accepts an int and
returns no result.
Defines a method called accept.
class Averager implements IntConsumer
{
private int total = 0;
private int count = 0;
public double average() {
return count > 0 ? ((double) total)/count : 0;
}
public void accept(int i) { total += i; count++; }
public void combine(Averager other) {
total += other.total;
count += other.count;
}
}
Averager averageCollect = people
.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.map(Person::getAge)
.collect(Averager::new, Averager::accept,
Averager::combine);
System.out.println("Average age of male members: " +
averageCollect.average());
Supplier - a factory function to
create new instances of the
result type
Accumulator - a function that
modifies the result container
Combiner - a function that
takes two result objects and
merges them into one
combined result
For most use cases we would probably want to
just run simple operations on a stream and get
some collection back as a result.
For this we can use Collectors:
List<String> namesOfMaleMembersCollect = people
.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.map(p -> p.getName())
.collect(Collectors.toList());
Map<Person.Sex, List<Person>> byGender = people
.stream()
.collect(
Collectors.groupingBy(Person::getGender));
5.
More Additions
Parallel Streams
Java streams also support parallel computation via parallelStream().
Just call it instead of stream() and the stream would be divided into
substreams and processed in a parallel manner.
This doesn’t guarantee faster execution times and really depends on
the hardware and application.
A big topic for another talk.
String.Join
String message = String.join(“-”, “Java”, “8”, “talk”);
Returns “java-8-talk”
Optional
A new object wrapper that helps handling null pointer exceptions
Essentially wraps any object and exposes methods to make the object
handle NULL cases
Optional
Initializing:
Optional<MyObject> myObject = Optional.empty();
Or
MyObject nonNullObject = new MyObject();
Optional<MyObject> myObject = Optional.of(nonNullObject);
Optional
Perform action if the object is not null:
myObject.ifPresent(System.out::println)
Optional
Only check if the object is null or not
myObject.isPresent()
Optional
Replace the ternary (? :) operator
MyObject newOne = myObject.orElse
(new MyObject());
Optional
The Optional class contains methods similar to streams:
filter, map etc. They can be used to achieve similar
behavior to streams.
New DateTime API
But read this if it’s relevant: https://dzone.com/articles/introducing-new-date-and-time
More Stuff
- Additions to concurrency API’s - For another talk.
- IntelliJ suggestions are now Java 8 Ready - USE THEM!!!
- Samples in these slides are based on:
http://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html
- Great code samples for Java 8 - https://github.com/java8/Java8InAction
- Great article about streams -
http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-
2177646.html
thanks!
Any questions?
@sharon_roz
Credits
Special thanks to all the people who made and released
these awesome resources for free:
Presentation template by SlidesCarnival
Photographs by Unsplash

Java 8 new features or the ones you might actually use

  • 1.
    JAVA 8 NEW FEATURES orthe ones you might actually use Sharon Rozinsky
  • 2.
    18/3/2014Release Date Java 8adoption is running six months ahead of the original predictions http://www.baeldung.com/java-8-adoption-march-2016
  • 4.
  • 5.
    Encapsulate a functionalityand pass it as an argument Replace the cumbersome syntax of anonymous functions
  • 6.
    Let’s try anexample - write a code to search a list of people by a certain criteria Attempt # 1 Attempt # 2 Attempt # 3
  • 7.
    public static voidprintPeopleWithinAgeRange( List<Person> people, int low, int high) { for (Person p : people) { if (low <= p.getAge() && p.getAge() < high) { p.printPerson(); } } }
  • 8.
    But what ifthe search criteria changes? Attempt # 1 Attempt # 2 Attempt # 3
  • 9.
    public static voidprintPeople(List<Person> people, CheckPerson tester) { for (Person p : people) { if (tester.test(p)) { p.printPerson(); } } }
  • 10.
    printPeople( people, new CheckPerson() { publicboolean test(Person p) { return p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25; } } );
  • 11.
    Okay - let’stry it with lambda’s Attempt # 1 Attempt # 2 Attempt # 3
  • 12.
    printPeople( people, (Person p) ->p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25 );
  • 13.
    CheckPerson must bea functional interface!
  • 14.
    Syntax Rules Basic (p1, p2,…) -> {statements}
  • 15.
    Syntax Rules Evaluate AndReturn p -> p.getAge() > 25
  • 16.
    Syntax Rules Multiple Statements p-> { int x = 25; return p > x; }
  • 17.
    Method References Use lambdaexpressions to reference methods. There are 4 kinds of method references:
  • 18.
  • 19.
  • 20.
    An interface withonly one abstract method. (possible to have more non abstract methods using default).
  • 21.
    Not a newconcept: Runnable, Callable, Comparator etc...
  • 22.
    We saw thatwe can create instances of functional interfaces using lambdas. *Remember the CheckPerson interface from the first example.
  • 23.
    @FunctionalInterface (not a mustif demands are met = only 1 method)
  • 24.
    The java.util.function packagecontains many built in functional interfaces: @FunctionalInterface public interface Predicate<T> { boolean test(T t); } Predicate<Person> canDrive = p -> p.getAge() > 16;
  • 25.
    The java.util.function packagecontains many built in functional interfaces: @FunctionalInterface public interface Function<T, R> { R apply(T t); } Function<String, Integer> intToString = x -> Integer.valueOf(x);
  • 26.
  • 27.
    Add functionality tointerfaces without breaking backward compatibility.
  • 28.
  • 29.
  • 30.
    Side effect ofOracle’s extensions to the collection interfaces.
  • 31.
  • 32.
    public interface Person{ void goSomewhere(Location location); } public Class NicePerson implements Person{ public void goSomewhere(Location location) { … } }
  • 33.
    Now Let’s adda method to the Person interface - void saySomething (String whatToSay)
  • 34.
    public interface Person{ void goSomewhere(Location location); default void saySomething (String whatToSay) { … Sysout.println(whatToSay); } }
  • 35.
    Adding a defaultmethod to an interface requires no additions to the implementing classes.
  • 36.
    Like any othermethod in the interface default methods are implicitly public
  • 37.
    Extending an interfacewith a default method: Default method is not mentioned - extended interface gets the default method.
  • 38.
    Extending an interfacewith a default method: Redeclaring the default method - method becomes abstract (and implementing class has to implement it).
  • 39.
    Extending an interfacewith a default method: Redefine the default method - override the method functionality.
  • 40.
    Any Famous ProblemYou Can Think Of?
  • 41.
  • 42.
    interface InterfaceA { defaultpublic void sayHi() { System.out.println("Hi from InterfaceA"); } } interface InterfaceB { default public void sayHi() { System.out.println("Hi from InterfaceB"); } } public class MyClass implements InterfaceA, InterfaceB { public static void main(String[] args) { ... } }
  • 43.
    interface InterfaceA { defaultpublic void sayHi() { System.out.println("Hi from InterfaceA"); } } interface InterfaceB { default public void sayHi() { System.out.println("Hi from InterfaceB"); } } public class MyClass implements InterfaceA, InterfaceB { public static void main(String[] args) { ... } } Compilation Error!
  • 44.
    Solution: - Provide implementationto sayHi in MyClass - Can use: InterfaceA.super.sayHi()
  • 45.
    Default methods arenever final Default methods cannot be synchronized Default methods are always public There are no fields in an interface - hard to maintain a state For most cases - classes define what an object is while an interface defines what an object can do Interfaces vs. Abstract Classes
  • 46.
  • 47.
    A new JavaAPI that helps processing data and collections in a declarative way. Formal definition: “A sequence of elements supporting sequential and parallel aggregate operations.”
  • 48.
    The Pipeline Approach Javastreams use a pipeline approach to perform the different tasks needed to process a given collection.
  • 49.
    A pipeline iscomposed of the following: Source - any structure that holds data: array, collection, I/O channel, generator functions, etc…
  • 50.
    A pipeline iscomposed of the following: Intermediate operations - 0 or more operations that produce a new stream. The basic examples for this are the Stream() and Filter() operations.
  • 51.
    A pipeline iscomposed of the following: Terminal operation - an operation that returns a non stream value e.g. primitives, collections or no value at all.
  • 52.
  • 53.
    double average =people .stream() .filter(p -> p.getGender() == Person.Sex.MALE) .mapToInt(Person::getAge) .average() .getAsDouble(); Produce a stream from the given collection
  • 54.
    double average =people .stream() .filter(p -> p.getGender() == Person.Sex.MALE) .mapToInt(Person::getAge) .average() .getAsDouble(); Filter on a predicate - produces another stream
  • 55.
    double average =people .stream() .filter(p -> p.getGender() == Person.Sex.MALE) .mapToInt(Person::getAge) .average() .getAsDouble(); Map only the age of each person - return a stream of type IntStream
  • 56.
    double average =people .stream() .filter(p -> p.getGender() == Person.Sex.MALE) .mapToInt(Person::getAge) .average() .getAsDouble(); Perform average on all values - returns an OptionalDouble
  • 57.
    double average =people .stream() .filter(p -> p.getGender() == Person.Sex.MALE) .mapToInt(Person::getAge) .average() .getAsDouble(); Return the final value
  • 58.
    int numberOfMales =0; int totalAge = 0; foreach(person p : people){ if(p.getGender() == Person.Sex.MALE){ numberOfMales++; totalAge += p.getAge(); } } if(numberOfMales > 0){ return totalAge / numberOfMales; } Old School Way:
  • 59.
    Reduce The average() operationfrom the previous example is one of many reduction methods (the terminal operations) The Java 8 API provides handy reduction operations but also a more generic method to perform reduction by yourself
  • 60.
    double agesSum =people .stream() .filter(p -> p.getGender() == Person.Sex.MALE) .mapToInt(Person::getAge) .reduce(0, (a,b) -> a + b) Identity - an initial and also default value if the stream is empty. Accumulator - an associative function
  • 61.
    reduce also hasa 3 parameter version that accepts an identity, a mapper which replaces the mapToInt in this case and a combiner function that serves as an accumulator
  • 62.
    Collect The reduce methodcreates a new value for every element that it processes. The collect method modifies an existing value. Think about creating the average ages in the last example (Yap it’s hard with reduce…). Let’s try it with collect:
  • 63.
    Before we begin: IntCosumer- a built in functional interface that accepts an int and returns no result. Defines a method called accept.
  • 64.
    class Averager implementsIntConsumer { private int total = 0; private int count = 0; public double average() { return count > 0 ? ((double) total)/count : 0; } public void accept(int i) { total += i; count++; } public void combine(Averager other) { total += other.total; count += other.count; } }
  • 65.
    Averager averageCollect =people .stream() .filter(p -> p.getGender() == Person.Sex.MALE) .map(Person::getAge) .collect(Averager::new, Averager::accept, Averager::combine); System.out.println("Average age of male members: " + averageCollect.average()); Supplier - a factory function to create new instances of the result type Accumulator - a function that modifies the result container Combiner - a function that takes two result objects and merges them into one combined result
  • 66.
    For most usecases we would probably want to just run simple operations on a stream and get some collection back as a result. For this we can use Collectors:
  • 67.
    List<String> namesOfMaleMembersCollect =people .stream() .filter(p -> p.getGender() == Person.Sex.MALE) .map(p -> p.getName()) .collect(Collectors.toList()); Map<Person.Sex, List<Person>> byGender = people .stream() .collect( Collectors.groupingBy(Person::getGender));
  • 68.
  • 69.
    Parallel Streams Java streamsalso support parallel computation via parallelStream(). Just call it instead of stream() and the stream would be divided into substreams and processed in a parallel manner. This doesn’t guarantee faster execution times and really depends on the hardware and application. A big topic for another talk.
  • 70.
    String.Join String message =String.join(“-”, “Java”, “8”, “talk”); Returns “java-8-talk”
  • 71.
    Optional A new objectwrapper that helps handling null pointer exceptions Essentially wraps any object and exposes methods to make the object handle NULL cases
  • 72.
    Optional Initializing: Optional<MyObject> myObject =Optional.empty(); Or MyObject nonNullObject = new MyObject(); Optional<MyObject> myObject = Optional.of(nonNullObject);
  • 73.
    Optional Perform action ifthe object is not null: myObject.ifPresent(System.out::println)
  • 74.
    Optional Only check ifthe object is null or not myObject.isPresent()
  • 75.
    Optional Replace the ternary(? :) operator MyObject newOne = myObject.orElse (new MyObject());
  • 76.
    Optional The Optional classcontains methods similar to streams: filter, map etc. They can be used to achieve similar behavior to streams.
  • 77.
  • 78.
    But read thisif it’s relevant: https://dzone.com/articles/introducing-new-date-and-time
  • 79.
    More Stuff - Additionsto concurrency API’s - For another talk. - IntelliJ suggestions are now Java 8 Ready - USE THEM!!! - Samples in these slides are based on: http://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html - Great code samples for Java 8 - https://github.com/java8/Java8InAction - Great article about streams - http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams- 2177646.html
  • 80.
  • 81.
    Credits Special thanks toall the people who made and released these awesome resources for free: Presentation template by SlidesCarnival Photographs by Unsplash