Java8 Quick Guide
Java8 Quick Guide
JAVA 8 - OVERVIEW
JAVA 8 is a major feature release of JAVA programming language development. Its initial version
was released on 18 March 2014. With the Java 8 release, Java provided supports for functional
programming, new JavaScript engine, new APIs for date time manipulation, new streaming API, etc.
New Features
Lambda expression − Adds functional processing capability to Java.
New tools − New compiler tools and utilities are added like ‘jdeps’ to figure out
dependencies.
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Comparator;
tester.sortUsingJava7(names1);
System.out.println(names1);
System.out.println("Sort using Java 8 syntax: ");
tester.sortUsingJava8(names2);
System.out.println(names2);
}
Here the sortUsingJava8() method uses sort function with a lambda expression as parameter to
get the sorting criteria.
For most of the examples given in this tutorial, you will find a Try it option in our website code
sections at the top right corner that will take you to the online compiler. So just make use of it and
enjoy your learning.
Java SE can be downloaded for free from the following link − Download Java.
Follow the instructions to download Java, and run the .exe to install Java on your machine. Once
you have installed Java on your machine, you would need to set environment variables to point to
correct installation directories.
Edit the 'C:\autoexec.bat' file and add the following line at the end − 'SET
PATH=%PATH%;C:\Program Files\java\jdk\bin'
For example, if you use bash as your shell, then you would add the following line at the end of your
'.bashrc: export PATH=/path/to/java:$PATH'
Notepad − On Windows machine, you can use any simple text editor like Notepad
(recommended for this tutorial) or TextPad.
Netbeans − It is a Java IDE that is open-source and free which can be downloaded from
http://www.netbeans.org/index.html.
Eclipse − It is also a Java IDE developed by the Eclipse open-source community and can be
downloaded from http://www.eclipse.org/.
Syntax
A lambda expression is characterized by the following syntax.
Optional type declaration − No need to declare the type of a parameter. The compiler
can inference the same from the value of the parameter.
Optional curly braces − No need to use curly braces in expression body if the body
contains a single statement.
Optional return keyword − The compiler automatically returns the value if the body has a
single expression to return the value. Curly braces are required to indicate that expression
returns a value.
Java8Tester.java
public class Java8Tester {
public static void main(String args[]){
Java8Tester tester = new Java8Tester();
//with parenthesis
GreetingService greetService1 = message ->
System.out.println("Hello " + message);
//without parenthesis
GreetingService greetService2 = (message) ->
System.out.println("Hello " + message);
greetService1.sayMessage("Mahesh");
greetService2.sayMessage("Suresh");
}
interface MathOperation {
int operation(int a, int b);
}
interface GreetingService {
void sayMessage(String message);
}
$javac Java8Tester.java
$java Java8Tester
10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Mahesh
Hello Suresh
Following are the important points to be considered in the above example.
Lambda expression eliminates the need of anonymous class and gives a very simple yet
powerful functional programming capability to Java.
Scope
Using lambda expression, you can refer to any final variable or effectively final variable (which is
assigned only once). Lambda expression throws a compilation error, if a variable is assigned a
value the second time.
Scope Example
Create the following Java program using any editor of your choice in, say, C:\> JAVA.
Java8Tester.java
interface GreetingService {
void sayMessage(String message);
}
}
$javac Java8Tester.java
$java Java8Tester
Hello! Mahesh
Static methods
Instance methods
Constructors using new operator (TreeSet::new)
import java.util.List;
import java.util.ArrayList;
names.add("Mahesh");
names.add("Suresh");
names.add("Ramesh");
names.add("Naresh");
names.add("Kalpesh");
names.forEach(System.out::println);
}
}
$javac Java8Tester.java
$java Java8Tester
Mahesh
Suresh
Ramesh
Naresh
Kalpesh
1 BiConsumer<T,U>
Represents an operation that accepts two input arguments, and returns no result.
2 BiFunction<T,U,R>
3 BinaryOperator<T>
Represents an operation upon two operands of the same type, producing a result of
the same type as the operands.
4 BiPredicate<T,U>
5 BooleanSupplier
6 Consumer<T>
Represents an operation that accepts a single input argument and returns no result.
7 DoubleBinaryOperator
8 DoubleConsumer
9 DoubleFunction<R>
10 DoublePredicate
11 DoubleSupplier
12 DoubleToIntFunction
13 DoubleToLongFunction
14 DoubleUnaryOperator
15 Function<T,R>
16 IntBinaryOperator
18 IntFunction<R>
19 IntPredicate
20 IntSupplier
21 IntToDoubleFunction
22 IntToLongFunction
23 IntUnaryOperator
24 LongBinaryOperator
25 LongConsumer
26 LongFunction<R>
27 LongPredicate
28 LongSupplier
29 LongToDoubleFunction
30 LongToIntFunction
31 LongUnaryOperator
32 ObjDoubleConsumer<T>
33 ObjIntConsumer<T>
34 ObjLongConsumer<T>
35 Predicate<T>
36 Supplier<T>
37 ToDoubleBiFunction<T,U>
38 ToDoubleFunction<T>
39 ToIntBiFunction<T,U>
Represents a function that accepts two arguments and produces an int-valued result.
40 ToIntFunction<T>
41 ToLongBiFunction<T,U>
Represents a function that accepts two arguments and produces a long-valued result.
42 ToLongFunction<T>
Represents a function that produces a long-valued result.
43 UnaryOperator<T>
Represents an operation on a single operand that produces a result of the same type
as its operand.
Create the following Java program using any editor of your choice in, say, C:\> JAVA.
Java8Tester.java
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
//pass n as parameter
eval(list, n->true);
if(predicate.test(n)) {
System.out.println(n + " ");
}
}
}
}
Here we've passed Predicate interface, which takes a single input and returns Boolean.
$java Java8Tester
Syntax
public interface vehicle {
default void print(){
System.out.println("I am a vehicle!");
}
}
Multiple Defaults
With default functions in interfaces, there is a possibility that a class is implementing two interfaces
with same default methods. The following code explains how this ambiguity can be resolved.
Second solution is to call the default method of the specified interface using super.
Java8Tester.java
interface Vehicle {
default void print(){
System.out.println("I am a vehicle!");
}
interface FourWheeler {
default void print(){
System.out.println("I am a four wheeler!");
}
}
$javac Java8Tester.java
$java Java8Tester
I am a vehicle!
I am a four wheeler!
Blowing horn!!!
I am a car!
JAVA 8 - STREAMS
Stream is a new abstract layer introduced in Java 8. Using stream, you can process data in a
declarative way similar to SQL statements. For example, consider the following SQL statement.
The above SQL expression automatically returns the maximum salaried employee's details,
without doing any computation on the developer's end. Using collections framework in Java, a
developer has to use loops and make repeated checks. Another concern is efficiency; as multi-
core processors are available at ease, a Java developer has to write parallel code processing that
can be pretty error-prone.
To resolve such issues, Java 8 introduced the concept of stream that lets the developer to process
data declaratively and leverage multicore architecture without the need to write any specific code
for it.
What is Stream?
Stream represents a sequence of objects from a source, which supports aggregate operations.
Following are the characteristics of a Stream −
Aggregate operations − Stream supports aggregate operations like filter, map, limit,
reduce, find, match, and so on.
Pipelining − Most of the stream operations return stream itself so that their result can be
pipelined. These operations are called intermediate operations and their function is to take
input, process them, and return output to the target. collect() method is a terminal operation
which is normally present at the end of the pipelining operation to mark the end of the
stream.
Automatic iterations − Stream operations do the iterations internally over the source
elements provided, in contrast to Collections where explicit iteration is required.
Generating Streams
With Java 8, Collection interface has two methods to generate a Stream.
stream() − Returns a sequential stream considering collection as its source.
forEach
Stream has provided a new method ‘forEach’ to iterate each element of the stream. The following
code segment shows how to print 10 random numbers using forEach.
map
The ‘map’ method is used to map each element to its corresponding result. The following code
segment prints unique squares of numbers using map.
filter
The ‘filter’ method is used to eliminate elements based on a criteria. The following code segment
prints a count of empty strings using filter.
limit
The ‘limit’ method is used to reduce the size of the stream. The following code segment shows how
to print 10 random numbers using limit.
sorted
The ‘sorted’ method is used to sort the stream. The following code segment shows how to print 10
random numbers in a sorted order.
Parallel Processing
parallelStream is the alternative of stream for parallel processing. Take a look at the following
code segment that prints a count of empty strings using parallelStream.
Statistics
With Java 8, statistics collectors are introduced to calculate all statistics when stream processing is
being done.
Stream Example
Create the following Java program using any editor of your choice in, say, C:\> JAVA.
Java8Tester.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.Map;
count = strings.stream().filter(string->string.isEmpty()).count();
System.out.println("Empty Strings: " + count);
filtered = strings.stream().filter(string -
>!string.isEmpty()).collect(Collectors.toList());
System.out.println("Filtered List: " + filtered);
mergedString = strings.stream().filter(string -
>!string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("Merged String: " + mergedString);
squaresList = numbers.stream().map( i -
>i*i).distinct().collect(Collectors.toList());
System.out.println("Squares List: " + squaresList);
System.out.println("List: " +integers);
random.ints().limit(10).sorted().forEach(System.out::println);
//parallel processing
count = strings.parallelStream().filter(string -> string.isEmpty()).count();
System.out.println("Empty Strings: " + count);
}
if(string.isEmpty()){
count++;
}
}
return count;
}
if(string.length() == 3){
count++;
}
}
return count;
}
if(!string.isEmpty()){
filteredList.add(string);
}
}
return filteredList;
}
if(!string.isEmpty()){
stringBuilder.append(string);
stringBuilder.append(separator);
}
}
String mergedString = stringBuilder.toString();
return mergedString.substring(0, mergedString.length()-2);
}
if(!squaresList.contains(square)){
squaresList.add(square);
}
}
return squaresList;
}
$javac Java8Tester.java
$java Java8Tester
Using Java 7:
List: [abc, , bc, efg, abcd, , jkl]
Empty Strings: 2
Strings of length 3: 3
Filtered List: [abc, bc, efg, abcd, jkl]
Merged String: abc, bc, efg, abcd, jkl
Squares List: [9, 4, 49, 25]
List: [1, 2, 13, 4, 15, 6, 17, 8, 19]
Highest number in List : 19
Lowest number in List : 1
Sum of all numbers : 85
Average of all numbers : 9
Random Numbers:
-1279735475
903418352
-1133928044
-1571118911
628530462
18407523
-881538250
-718932165
270259229
421676854
Using Java 8:
List: [abc, , bc, efg, abcd, , jkl]
Empty Strings: 2
Strings of length 3: 3
Filtered List: [abc, bc, efg, abcd, jkl]
Merged String: abc, bc, efg, abcd, jkl
Squares List: [9, 4, 49, 25]
List: [1, 2, 13, 4, 15, 6, 17, 8, 19]
Highest number in List : 19
Lowest number in List : 1
Sum of all numbers : 85
Average of all numbers : 9.444444444444445
Random Numbers:
-1009474951
-551240647
-2484714
181614550
933444268
1227850416
1579250773
1627454872
1683033687
1798939493
Empty Strings: 2
Class Declaration
Following is the declaration for java.util.Optional<T> class −
Class Method
If a value is present and the value matches a given predicate, it returns an Optional
describing the value, otherwise returns an empty Optional.
5 T get()
6 int hashCode()
Returns the hash code value of the present value, if any, or 0 (zero) if no value is
present.
7 void ifPresent(Consumer<? super T> consumer)
If a value is present, it invokes the specified consumer with the value, otherwise does
nothing.
8 boolean isPresent()
If a value is present, applies the provided mapping function to it, and if the result is
non-null, returns an Optional describing the result.
12 T orElse(T other)
Returns the value if present, otherwise invokes other and returns the result of that
invocation.
15 String toString()
java.lang.Object
Optional Example
Create the following Java program using any editor of your choice in, say, C:\> JAVA.
Java8Tester.java
import java.util.Optional;
$javac Java8Tester.java
$java Java8Tester
jjs
For Nashorn engine, JAVA 8 introduces a new command line tool, jjs, to execute javascript codes
at console.
Interpreting js File
Create and save the file sample.js in c:\> JAVA folder.
sample.js
print('Hello World!');
Hello World!
$jjs
jjs> print("Hello, World!")
Hello, World!
jjs> quit()
>>
Pass Arguments
Open the console and use the following command.
$jjs -- a b c
jjs> print('letters: ' +arguments.join(", "))
letters: a, b, c
jjs>
Example
Create the following Java program using any editor of your choice in, say, C:\> JAVA.
Java8Tester.java
import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
$javac Java8Tester.java
Now run the Java8Tester as follows −
$java Java8Tester
Mahesh
12
sample.js
$jjs sample.js
78952000000000000003.20
Not thread safe − java.util.Date is not thread safe, thus developers have to deal with
concurrency issue while using date. The new date-time API is immutable and does not have
setter methods.
Poor design − Default Date starts from 1900, month starts from 1, and day starts from 0, so
no uniformity. The old API had less direct methods for date operations. The new API provides
numerous utility methods for such operations.
Difficult time zone handling − Developers had to write a lot of code to deal with timezone
issues. The new API has been developed keeping domain-specific design in mind.
Java 8 introduces a new date-time API under the package java.time. Following are some of the
important classes introduced in java.time package.
Java8Tester.java
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
import java.time.Month;
//parse a string
LocalTime date5 = LocalTime.parse("20:15:30");
System.out.println("date5: " + date5);
}
}
$javac Java8Tester.java
$java Java8Tester
Create the following Java program using any editor of your choice in, say, C:\> JAVA.
Java8Tester.java
import java.time.ZonedDateTime;
import java.time.ZoneId;
ZoneId id = ZoneId.of("Europe/Paris");
System.out.println("ZoneId: " + id);
$javac Java8Tester.java
$java Java8Tester
date1: 2007-12-03T10:15:30+05:00[Asia/Karachi]
ZoneId: Europe/Paris
CurrentZone: Etc/UTC
Create the following Java program using any editor of your choice in, say, C:\> JAVA.
Java8Tester.java
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
$javac Java8Tester.java
$java Java8Tester
Create the following Java program using any editor of your choice in, say, C:\> JAVA.
Java8Tester.java
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.time.Duration;
import java.time.Period;
public class Java8Tester {
public static void main(String args[]){
Java8Tester java8tester = new Java8Tester();
java8tester.testPeriod();
java8tester.testDuration();
}
$javac Java8Tester.java
$java Java8Tester
Temporal Adjusters
TemporalAdjuster is used to perform the date mathematics. For example, get the "Second
Saturday of the Month" or "Next Tuesday". Let us see them in action.
Create the following Java program using any editor of your choice in, say, C:\> JAVA.
Java8Tester.java
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.time.DayOfWeek;
$javac Java8Tester.java
$java Java8Tester
Backward Compatibility
A toInstant() method is added to the original Date and Calendar objects, which can be used to
convert them to the new Date-Time API. Use an ofInstant(Insant,ZoneId) method to get a
LocalDateTime or ZonedDateTime object. Let us see them in action.
Create the following Java program using any editor of your choice in, say, C:\> JAVA.
Java8Tester.java
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.Date;
import java.time.Instant;
import java.time.ZoneId;
$javac Java8Tester.java
$java Java8Tester
JAVA 8 - BASE64
With Java 8, Base64 has finally got its due. Java 8 now has inbuilt encoder and decoder for Base64
encoding. In Java 8, we can use three types of Base64 encoding.
Simple − Output is mapped to a set of characters lying in A-Za-z0-9+/. The encoder does
not add any line feed in output, and the decoder rejects any character other than A-Za-z0-
9+/.
URL − Output is mapped to set of characters lying in A-Za-z0-9+_. Output is URL and
filename safe.
MIME − Output is mapped to MIME friendly format. Output is represented in lines of no more
than 76 characters each, and uses a carriage return '\r' followed by a linefeed '\n' as the line
separator. No line separator is present to the end of the encoded output.
Nested Classes
This class implements a decoder for decoding byte data using the Base64 encoding
scheme as specified in RFC 4648 and RFC 2045.
This class implements an encoder for encoding byte data using the Base64 encoding
scheme as specified in RFC 4648 and RFC 2045.
Methods
Returns a Base64.Decoder that decodes using the Basic type base64 encoding
scheme.
Returns a Base64.Encoder that encodes using the Basic type base64 encoding
scheme.
Returns a Base64.Decoder that decodes using the MIME type base64 decoding
scheme.
4
static Base64.Encoder getMimeEncoder()
Returns a Base64.Encoder that encodes using the MIME type base64 encoding
scheme.
Returns a Base64.Encoder that encodes using the MIME type base64 encoding
scheme with specified line length and line separators.
Returns a Base64.Decoder that decodes using the URL and Filename safe type base64
encoding scheme.
Returns a Base64.Encoder that encodes using the URL and Filename safe type base64
encoding scheme.
Methods Inherited
This class inherits methods from the following class −
java.lang.Object
Base64 Example
Create the following Java program using any editor of your choice in say C:/> JAVA.
Java8Tester.java
import java.util.Base64;
import java.util.UUID;
import java.io.UnsupportedEncodingException;
// Decode
byte[] base64decodedBytes = Base64.getDecoder().decode(base64encodedString);
$javac Java8Tester.java
$java Java8Tester