Java 8 is a powerful release of Java Platform, give us a big of change from JVM to language and libraries.
Lambda Expressions
Lambda Expressions is a new feature of Java 8 that makes Java code more clearly and easily for development.
static int doMathOperation(int a, int b, IMathOperation mathOperation) { return mathOperation.run(a, b); } public static void main(String[] args) { IMathOperation addition = (int a, int b) -> a + b; IMathOperation subtraction = (int a, int b) -> a - b; IMathOperation multiplication = (int a, int b) -> a * b; System.out.println(doMathOperation(2, 1, addition)); System.out.println(doMathOperation(2, 1, subtraction)); System.out.println(doMathOperation(2, 1, multiplication)); }
Syntax:
Argument List | Arrow Token | Body | Note |
---|---|---|---|
(arg1, arg2…) | -> | { body } | |
(int a, int b) | -> | a + b | with type declaration |
(a, b) | -> | a + b | no type declaration |
(int a, int b) | -> | {return (a + b)} | with return statement |
a | -> | a*a*a | no parenthesis |
() | -> | 42 | no arguments |
(String s) | -> | {System.out.print(s);} | returns nothing |
– A lambda expression can have zero, one or more parameters.
– No need to declare type of a parameter.
– No need to write parenthesis around parameter if there is only one parameter (required if more).
– No need to use curly braces in expression body if there is only one statement (required if more).
– No need to use return keyword if there is only one statement. The compiler returns the value automatically.
>>> More details at: Java 8 – Lambda Expressions
Functional Interfaces
Functional Interfaces is an interface with only one abstract method inside.
public interface MyFuncInterface { void doWork(); }
@FunctionalInterface annotation is used to annotate for Functional Interface. So compiler will throw errors when the interface is not a valid Functional Interface.
@FunctionalInterface public interface MyFuncInterface { void doWork(); void doAnotherWork(); }
Invalid '@FunctionalInterface' annotation; MyFuncInterface is not a functional interface
Apply Functional Interfaces:
@FunctionalInterface public interface MyFuncInterface { void doWork(); } public class MainApp { public static void executeFunction(MyFuncInterface func) { func.doWork(); } public static void main(String[] args) { executeFunction(new MyFuncInterface() { @Override public void doWork() { System.out.println("invoke Function using Anonymous Inner Class"); } }); // with Lambda Expression executeFunction(() -> System.out.println("invoke Function using Lambda Expression")); } }
For Functional Interface with only one method, we can make code lean and beautiful with Lambda Expression, it seem like that we pass a method as argument to a function.
>>> More details at: Java 8 – Functional Interfaces
Method References
Method reference points to the method by its name by replacing a single-method lambda expression.
The syntax of a Method reference is: Object/Class/Type :: methodName
For example, the lambda expression:
s -> System.out.print(s)
can be replaced with the method reference:
System.out::print
There are four kinds of method references:
– Reference to a static method: ContainingClass::staticMethodName
– Reference to an instance method of a particular object: containingObject::instanceMethodName
– Reference to an instance method of an arbitrary object of a particular type: ContainingType::instanceMethodName
– Reference to a constructor: ClassName::new
>>> More details at: Java 8 – Method References
Streams
A stream is an abstract concept that represents a sequence of objects created by a source, it’s neither a data structure nor a collection object where we can store items. So we can’t point to any location in the stream, we just interact with items by specifying the functions.
Listnumbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); // get List from Stream Operation List result = numbers.stream() .filter(i -> (i % 2) == 0) .map(i -> "[" + i + "]") .collect(Collectors.toList()); System.out.println(result);
Run the code above, the console shows:
[[2], [4], [6], [8]]
Now, we have concept of using a Stream is to enable functional-style operations on streams of elements. Those operations are composed into a stream pipeline which consists of:
Source
> Intermediate Operations
> Terminal Operation
– a source (in the example, it is a collection – List, but it is also an array, a generator function, an I/O channel…)
– intermediate operations (which transform current stream into another stream at the current chain, in the example, filter is the first operation and map is the second one)
– a terminal operation (which produces a result or side-effect, in the example, it is collect)
>>> More details at: Java 8 – Streams
Optional Class
Null reference causes many problems because it often denotes the absence of a value. Java 8 Optional is a new class that can help us handle these cases instead of checking null.
Instead of Null checking before doing something:
String text = ...; if (text != null) { System.out.println(text); }
We can use Optionnal ifPresent()
method alternatively:
String text = ...; OptionalopText= Optional.ofNullable(text); opText.ifPresent(s -> System.out.println(s));
>>> More details at: Java 8 – Optional
New Date/Time API
Java 8 provides lots of new Date Time APIs:
– Local Date – Time
– Plus and Minus Date – Time
– TemporalAdjusters
– Period & Duration
– TimeZone
– Formatting and Parsing
>>> More details at: Java 8 – Date Time
Base64
Java 8 Base64 provides a standard way to do Base64 encoding and decoding.
There are three types of Base64 encoding:
– Basic: Encoder produces a set of characters within A-Za-z0-9+/. Decoder rejects any character NOT mapped to A-Za-z0-9+/.
– URL: Encoder produces a URL or safe filename which is set of characters within A-Za-z0-9+_.
– MIME: Output is mapped to MIME friendly format.
>>> More details at: Java 8 – Base64
Multithreading – CompletableFutures
Java 8 multithreading programming has an important feature named CompletableFuture. Java has the concept of a Future object, which can help program make something done while waiting for other things. However, although program can inspect Future objects to see if they’re done, what if program want to execute some code whenever its ready? It still has to wait until the result is available. CompletableFuture meets the requirement, and more than that.
Using one of those factory methods to create a CompletableFuture object:
static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier); static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor); static CompletableFuture<Void> runAsync(Runnable runnable); static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor);
If we don’t provide any Executor object as input parameter, the method will use ForkJoinPool.commonPool()
private static final boolean useCommonPool = (ForkJoinPool.getCommonPoolParallelism() > 1); /** * Default executor -- ForkJoinPool.commonPool() unless it cannot * support parallelism. */ private static final Executor asyncPool = useCommonPool ? ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
In this example, we use that global, general purpose pool ForkJoinPool.commonPool()
:
CompletableFuture.supplyAsync(new Supplier() { @Override public String get() { try { System.out.println("inside future: waiting for detecting..."); // process data System.out.println("inside future: done..."); return numbers.get(index); } catch (Throwable e) { return "not detected"; } } });
>>> More details at:
– Java 8 CompletableFutures
– Java 8 Multiple CompletableFutures
– Java 8 CompletableFuture Handle Exception
How to – Practice
– How to use Stream Filter in Java 8 with List & Array Examples
– How to use Java 8 Stream Map Examples with a List or Array
– How to use Java 8 Stream FlatMap Examples with List, Array
– How to use Java 8 Stream Reduce Examples with List and Array
– Java 8 Stream.collect() – Stream.Collectors APIs Examples
– How to use Java 8 Stream Collectors.groupingBy() Examples
Java 8 – Misc
– Java Read Text File by BufferedReader, Java 7,Java 8
– How to use Java 8 Encode (Decode) an Image to Base64
– Java 8 – How to convert List to Map & Map to List
– How to use String Joiner with Java 8
– Ways to convert an InputStream to String
– How to compare Dates in Java
All articles: Java 8