21
Software Engineering Computer Science Engineering School Francisco Ortin University of Oviedo New Functional Features of Java 8

New Functional Features of Java 8

Embed Size (px)

DESCRIPTION

On March 2014, Java 8 was released. These informal slides describe the new elements of the programming languages, focusing on those taken from the functional paradigm.

Citation preview

Page 1: New Functional Features of Java 8

Software

Engineering

Computer Science

Engineering School

Francisco Ortin University of Oviedo

New Functional Features

of Java 8

Page 2: New Functional Features of Java 8

Francisco Ortín Soler

Disclaimer

• This slides are aimed at briefly explaining the new functional features of Java 8

• It is an informal document

• The code used in this slides is available athttp://www.reflection.uniovi.es/download/2014/java8.zip

• It has been compiled and executed with Java SE Development Kit 8.0

March 20th, 2014

Francisco Ortin

ortin at lsi.uniovi.es

Page 3: New Functional Features of Java 8

Francisco Ortín Soler

Java 8

• Java 8 has been released on March 2014

• It includes some features of the functional paradigm such as:

Lambda expressions

Method references

Types of some typical lambda expressions

Streams (aggregate operations)

Closures (constant variables of the enclosing block)

• It also provides default method implementations for interfaces

Page 4: New Functional Features of Java 8

Francisco Ortín Soler

Lambda Expressions

• Lambda expressions are provided

The -> symbol separates parameters from body

Parameter types can be optionally specified

Parenthesis are not mandatory when only one parameter is passed

If the body is just one expression, return and { }are not required

String[] words = new String [] {

"Hello", "from", "Java", "8" };

Arrays.sort(words,

(word1, word2) -> word1.length() - word2.length()

);

Page 5: New Functional Features of Java 8

Francisco Ortín Soler

Types of Lambda Expressions

• Lambda expressions promote to interfaces with one abstract method with the same signature as the lambda expression

• This kind of interfaces are called Functional Interfaces

The @FunctionalInterface annotation can be used

It is optional; helpful for detecting errors

@FunctionalInterface // not mandatory

interface MyPredicate<T> {

boolean exec(T element);

}

Page 6: New Functional Features of Java 8

Francisco Ortín Soler

Types of Lambda Expressions

@FunctionalInterface // not mandatory

interface MyPredicate<T> {

boolean exec(T element);

}

class Promotion {

static <T> T find(T[] collection, MyPredicate<T> predicate) {

for(T item : collection)

if (predicate.exec(item))

return item;

return null;

}

public static void main(String... args) {

Integer[] numbers = new Integer [] { 1, 2, 3 };

int number = find(numbers, n -> n % 2 == 0);

System.out.println(number);

}

}

Page 7: New Functional Features of Java 8

Francisco Ortín Soler

Method References

• Sometimes, a lambda expression does nothing but calling an existing method

• In those cases, the existing method can be referred by name

• For this purpose, the :: operator has been added to Java 8

• Static (class) methods are referred with Class::method

class MethodReferences {

static boolean isOdd(Integer number) {

return number %2 != 0;

}

public static void main(String... args) {

Integer[] numbers = new Integer [] { 1, 2, 3 };

Integer number = Promotion.find(numbers, MethodReferences::isOdd);

number = Promotion.find(numbers, new EqualTo(3)::compare);

}

}

Page 8: New Functional Features of Java 8

Francisco Ortín Soler

Method References

• Instance methods are referred with object::method

• Since these methods are associated to an object (this), they can be stateful

class EqualTo {

private int value;

public EqualTo(int value) { this.value = value; }

public boolean compare(Integer n) { return value == n; }

}

public class MethodReferences {

public static void main(String... args) {

Integer[] numbers = new Integer [] { 1, 2, 3 };

Integer number = Promotion.find(numbers,

new EqualTo(3)::compare);

}

}

Page 9: New Functional Features of Java 8

Francisco Ortín Soler

Types of Typical Lambda Exprs

• The package java.util.function provides types

(functional interfaces) of typical lambda functions

Function<T,R>: Function that receives a T argument and returns a R result

Predicate<T>: Predicate of one T argument

Consumer<T>: An operation that accepts a single Targument and returns no result

Supplier<T>: Function with no parameter returning a T value

UnaryOperator<T>: Operation on a single T operand, producing a T result

BinaryOperator<T>: Operation upon two Toperands, producing a result of the same type as the operands

Page 10: New Functional Features of Java 8

Francisco Ortín Soler

Types of Typical Lambda Exprs

• Notice: the methods of the interfaces must be explicitly called, and they are named differently (test, accept, apply, get…)

public static void main(String... args) {

MyPredicate<Integer> even = n -> n%2 == 0; // my own type

Predicate<Integer> odd = n -> n%2 != 0;

System.out.println(even.exec(number) + " " + odd.test(number));

Consumer<Integer> printAction = n -> System.out.println(n);

printAction.accept(number);

Function<Integer,Double> sqrt = n -> Math.sqrt(n);

System.out.println(sqrt.apply(number));

Supplier<Integer> random = () -> (int)(Math.random()*1000 - 1000/2);

System.out.println(random.get());

BinaryOperator<Integer> times = (a,b) -> a*b;

System.out.printf(times.apply(3,2));

}

Page 11: New Functional Features of Java 8

Francisco Ortín Soler

Types of Typical Lambda Exprs

• Since generics is implemented in Java with type erasure (i.e., T is Object), the previous types

have specific versions for built-in types:

And more…http://download.java.net/jdk8/docs/api/java/util/function/package-summary.html

Predicate<T> Supplier<T> Consumer<T> Function<T,R>

DoublePredicate BooleanSupplier DoubleConsumer DoubleFunction<R>

IntPredicate DoubleSupplier IntConsumer IntFunction<R>

LongPredicate IntSupplier LongConsumer IntToDoubleFunction

LongSupplier IntToLongFunction

LongFunction<R>

Page 12: New Functional Features of Java 8

Francisco Ortín Soler

Streams with Aggregate Operations

• The new java.util.stream package provides an API to

support functional-style operations on streams

• A stream is a sequence of elements

It is not a data structure that stores elements (i.e. a collection)

• They support sequential and parallel functional-style aggregate operations

• Operations are composed into a stream pipeline

• Pipeline consists of

A source (array, collection, generator, I/O channel…)

Intermediate aggregate operations

And a terminal operation, producing a result

• Computation on the source data is only performed when the terminal operation is initiated (kind of lazy)

Page 13: New Functional Features of Java 8

Francisco Ortín Soler

Streams (Aggregate Operations)

public class Streams {

static int compute(Collection<Integer> collection) {return collection.stream()

.filter(n -> n%2 == 0) // even numbers

.map(n -> n*n) // square

.reduce(0, (acc, item) -> acc + item); // summation}

public static void main(String... args) {System.out.println(compute(Arrays.asList(1, 2, 3, 4, 5)));

System.out.println(Arrays.asList(Stream.iterate(1, n -> n+1)

.skip(10)

.limit(5)

.toArray(Integer[]::new)));

}}

source

aggregate operations

terminal operation

source (infinite)

aggregate operations

terminal operation

• Similar to .NET LINQ

• There will be database streams eventually?

Page 14: New Functional Features of Java 8

Francisco Ortín Soler

Closures

• Lambda expressions can capture variables of the enclosing scope

• They do not have shadowing issues (a new scope is not created, being lexically scoped)

• Captured variables must be final or effectively final (their value cannot be modified)

public class Closures {

static Function<Integer,Integer> createClosure(int initialValue) {

int number = initialValue; // must be constant

return n -> number + n;

}

public static void main(String... args) {

Function<Integer,Integer> closure1 = createClosure(1);

System.out.println(closure1.apply(7) );

Function<Integer,Integer> closure10 = createClosure(10);

System.out.println(closure10.apply(7) );

}

}

Page 15: New Functional Features of Java 8

Francisco Ortín Soler

Closures

• Since functions are objects, they can represent functions with a mutable state

class Fibonacci implements Supplier<Integer> {

private int previous = 0, current = 1;

@Override

public Integer get() {

int next = current + previous;

previous = current;

current = next;

return previous;

}

public static void main(String... args) {

System.out.println(Arrays.asList(

Stream.generate(new Fibonacci()).limit(10)

.toArray(Integer[]::new)

));

}

}

Page 16: New Functional Features of Java 8

Francisco Ortín Soler

Default Methods

• Java 8 provides default implementations for interface methods (the default keyword is used), similar to mixins

@FunctionalInterface interface Comparator<T> {

int compare(T a, T b);

default Comparator<T> reversed() { return (a, b) -> this.compare(b,a); }

}

public class DefaultMethods {

public static <T> T max(T a, T b, Comparator<T> comp) {

return comp.compare(a,b)<0 ? a : b;

}

public static <T> T min(T a, T b, Comparator<T> comp) {

return max(a, b, comp.reversed());

}

public static void main(String... args) {

Comparator<String> comparator = (a,b) -> a.length() - b.length();

System.out.println(max("hello", "bye", comparator));

System.out.println(min("hello", "bye", comparator));

} }

Page 17: New Functional Features of Java 8

Francisco Ortín Soler

Multiple Inheritance

• As with multiple inheritance languages, different implementations of the same method may be inherited

• However, the Java compiler checks this condition, reporting an error

interface A {

default void m() { System.out.println("A::m"); }

}

interface B {

default void m() { System.out.println("B::m"); }

}

public class MultipleInheritance

implements A, B { // compiler error

}

Page 18: New Functional Features of Java 8

Francisco Ortín Soler

Multiple Inheritance

• Besides, a default method cannot be inherited if the class implements another interface with that method (even without a default implementation)

interface A {

default void m() { System.out.println("A::m"); }

}

interface C {

void m();

}

class MyClass implements A, C { // compiler error

}

Page 19: New Functional Features of Java 8

Francisco Ortín Soler

Multiple Inheritance

• Java 8 allows diamond inheritance: the most specific (derived) method implementation is called

interface A {

default void m() { System.out.println("A::m"); }

}

interface A1 extends A {}

interface A2 extends A {

default void m() { System.out.println("A2::m"); }

}

class Diamond implements A1, A2 {

public static void main(String... args) {

new Diamond().m(); // A2::m

A1 a1 = new Diamond();

a1.m();

} }

Page 20: New Functional Features of Java 8

Francisco Ortín Soler

Static Methods

• Java 8 allows interfaces to implement static methods to provide utility methods

• The static methods specific to an interface can be kept in the same interface rather than in a separate class

@FunctionalInterface

interface Comparator<T> {

int compare(T a, T b);

static <T extends Comparable<T>> Comparator<T> naturalOrder() {

return (a,b) -> a.compareTo(b);

}

}

public class DefaultMethods {

public static void main(String... args) {

System.out.println(

max("hello", "bye", Comparator.naturalOrder()

));

} }

Page 21: New Functional Features of Java 8

Software

Engineering

Computer Science

Engineering School

Francisco Ortin University of Oviedo

New Functional Features

of Java 8