Deep Dive
JAVA SE 8
AND
JAVA EE 7
CONTEXT
ROUTE TO GLORY
BEST PRACTICE
A method or technique that has consistently shown results superior to those
achieved with other means
WHAT ARE WE GOING TO TASTE
Java SE 8
LAMBDA EXPRESSIONS
▪ Anonymous methods
▪ Function
▪ Passed around
▪ Concise
A block of code that you can pass around so it can be executed later,
once or multiple times
INTRODUCTION TO LAMBDA
Old Way
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
class NameComparator implements Comparator<String> {
@Override
public int compare(final String name, final String anotherName) {
return name.compareTo(anotherName);
}
}
Collections.sort(names, new NameComparator());
INTRODUCTION TO LAMBDA
Better Way
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(final String name, final String anotherName) {
return name.compareTo(anotherName);
}
});
Lambda Way
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
Collections.sort(names,(String a, String b) -> { return a.compareTo(b);} );
INTRODUCTION TO LAMBDA
(String a, String b) -> { return a.compareTo(b);}
(arguments) -> {body}
LAMBDA EXAMPLE
Write it like a method
(String first, String second) -> {
if (first.length() < second.length()) return -1;
else if (first.length() > second.length()) return 1;
else return 0;
}
Even without param
() -> { for (int i = 0; i < 1000; i++) doWork(); }
▪ Make use of parameter type inference
▪ Only specify the types when compiler needs it
▪ Do not use parameter brackets when optional
LAMBDA – TYPE INFERENCE
// Avoid
Comparator<String> comp = (String a, String b) ->
a.compareTo(b);
(Integer t) -> System.out.println(t);
// Prefer
Comparator<String> comp = (a, b) ->
a.compareTo(b);
t -> System.out.println(t);
▪ Lambda expression to return a value in all branch
▪ Not allowed to return a value in some branches
LAMBDA – RETURN CONDITION
// Prefer
(int x) -> {
if (x >= 0) return 1;
else return 0;
}
// Error
(int x) -> {
if (x >= 0) return 1;
}
▪ A block of code and Parameters
▪ Values for the free variables
LAMBDA – VARIABLE SCOPE
public static void repeatMessage( String text, int count ) {
Runnable r = () -> {
for (int i = 0; i < count ; i++) {
System.out.println( text );
}
};
new Thread(r).start();
}
free variable
String text, int count
text
count
▪ Do not declare local variables as final
▪ Use new “effectively final” concept
LAMBDA – VARIABLE SCOPE
public static void orderByName( List<String> names ) {
int first = 0;
Comparator<String> comp = (first, second) -> first.compareTo(second);
Collections.sort(names, comp);
}
Effective finalList<String> names
names,
LAMBDA – VARIABLE SCOPE
for (int i = 0; i < n; i++) {
new Thread(() -> System.out.println( i )).start();
// Error—cannot capture i
}
▪ Reference variables value is not allowed to change
▪ Parameters are effective final
for (String arg : args) {
new Thread(() -> System.out.println( arg )).start();
}
Reference variable
is not fixed
i
i
Effective final
arg
arg
▪ Lambda expression can not mutate
LAMBDA – VARIABLE SCOPE
public class LambdaNonFinalExample {
static boolean odd = false;
public static void main(String[] args) throws Exception {
runLambda(() -> odd = true);
System.out.println("Odd=" + odd);
}
public static void runLambda(Callable c) throws Exception {
c.call();
}
}
Not possible to mutate
boolean odd = false;
runLambda(() -> odd = true);
LAMBDA – EXCEPTION HANDLING
public Supplier<?> createInstance(final String className) {
return () -> { Class.forName(className).newInstance() };
}
Functional interfaces not allowed for a checked exception
to be thrown
Class.forName(className).newInstance()
▪ Catch the exception inside the lambda expression
LAMBDA – EXCEPTION HANDLING
public Supplier<?> createInstance(final String className) {
return () -> {
try {
return Class.forName(className).newInstance();
} catch( ClassNotFoundException | IllegalAccessException | InstantiationException e ) {
throw new RuntimeException(e);
}
};
}
try {
return Class.forName(className).newInstance();
} catch( ClassNotFoundException | IllegalAccessException | InstantiationException e ) {
throw new RuntimeException(e);
}
▪ Handle the exception using Consumer
LAMBDA – EXCEPTION HANDLING
Better Way
public Supplier<?> createInstance(final String className, final Consumer<? super Throwable> consumer ) {
return () -> {
try {
return Class.forName(className).newInstance();
} catch( ClassNotFoundException | IllegalAccessException | InstantiationException e ) {
consumer.accept(e);
return null;
}
};
}
Consumer<? super Throwable> consumer
consumer.accept(e);
Java SE 8
FUNCTIONAL INTERFACE
▪ An Interface with a single abstract method
▪ Runnable
▪ Comparable
▪ Callable
▪ Java SE 8 new functional interfaces
▪ Function<T,R>
▪ Predicate<T>
▪ Supplier<T>
▪ Consumer<T>
FUNCTIONAL INTERFACES
An interface which has Single Abstract Method
▪ Functional interface must have a single abstract method
▪ Supply a lambda whenever an object of an interface with a single abstract method
▪ Tag any functional interface with the @FunctionalInterface annotation
FUNCTION
Purpose is to return any result by working on
a single input argument
▪ It accepts an argument of type T
▪ Returns a result of type R
▪ Applying specified logic on the input via the apply method
FUNCTION
Function<String, Integer> stringToInt = x -> Integer.valueOf(x);
stringToInt.apply("4");
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
Output
4
PREDICATE
Function for checking a condition
▪ Accepting a single argument to evaluate to a boolean result
▪ It has a single method test which returns the boolean value
FUNCTION
Predicate<String> emptyStringChecker = s -> s.isEmpty();
emptyStringChecker.test(“JAVA8");
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
Output
false
CONSUMER
Perform operations on the arguments
▪ Accepts a single argument but does not return any result
▪ Used to perform operations on the arguments
▪ Persisting
▪ Invoking house keeping operations
▪ Emailing
▪ Etc..
CONSUMER
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
final List<String> names = Arrays.asList("ganesan", "balaji", "venky", "Raju", "pavan");
names.forEach(new Consumer<String>() {
public void accept(final String name) {
System.out.println(name);
}
});
SUPPLIER
Supplies us with a result
▪ Accepts a single argument but does not return any result
▪ Used to fetching values
▪ Configuration values from database
▪ Loading with reference data
▪ Creating an list of data with default identifiers
▪ Etc..
SUPPLIER
@FunctionalInterface
public interface Supplier<T> {
T get();
}
FUNCTIONAL INTERFACES
Function that expects two arguments but produces a result by
operating on these two arguments
▪ BiPredicate
▪ BiConsumer
▪ BiFunction
DECLARING OWN FUNCTIONAL INTERFACE
We can declare our own Functional Interface by defining Single
Abstract Method in interface
▪ Can tag any functional interface with @FunctionalInterface
▪ Compiler checks entity is an interface with a single abstract
method
▪ Javadoc page includes a statement that your interface is a
functional interface
▪ It is not required to use the annotation
▪ Any interface with a single abstract method is, by definition, a functional interface
▪ Using the @FunctionalInterface annotation is a good idea.
DECLARING OWN FUNCTIONAL INTERFACE
// Not Correct
@FunctionalInterface
public interface FunctionalInterfaceTest{
void display();
void anotherDisplay();
}
// Correct
@FunctionalInterface
public interface FunctionalInterfaceTest{
void display();
}
AVOID METHOD OVERLOAD
▪ Lambdas use target typing
▪ Clashes with method overloading
// avoid
public class Foo<T> {
public Foo<R> apply(Function<T, R> fn);
public Foo<T> apply(UnaryOperator<T> fn);
}
AVOID METHOD OVERLOAD
▪ Lambdas use target typing
▪ Clashes with method overloading
▪ Use different method names to avoid clashes
// prefer
public class Foo<T> {
public Foo<R> applyFunction(Function<T, R> fn);
public Foo<T> applyOperator(UnaryOperator<T> fn);
}
METHOD REFERENCE
Accept reference to a method where an implementation of a
functional interface is expected
(String s) -> System.out.println(s)
System.out::println
Where :: signifies that System.out'svoid
println(String s) method is being referenced
METHOD REFERENCE
▪ Reference to a static method
▪ className::staticMethodName
▪ Reference to an instance method of a particular object
▪ objectName::instanceMethodName
▪ Reference to an instance method of an arbitrary object of a particular type
▪ className::instanceMethodName
▪ Reference to a constructor
▪ className::new. className
METHOD REFERENCE
class ComparisonProvider {
public int compareByName(Person a, Person b) {
return a.getName().compareTo(b.getName());
}
public int compareByAge(Person a, Person b) {
return a.getBirthday().compareTo(b.getBirthday());
}
}
ComparisonProvider myComparisonProvider = new ComparisonProvider();
Arrays.sort(rosterAsArray, myComparisonProvider::compareByName );myComparisonProvider::compareByName
compareByName
METHOD REFERENCE
String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert"};
Arrays.sort(stringArray, String::compareToIgnoreCase);String::compareToIgnoreCase
Many languages integrate function expressions with their collections library
DEFAULT METHOD - INTRO
Old Way
for (int i = 0; i < names.size(); i++) {
System.out.println(list.get(i));
}
final List<String> names = Arrays.asList("ganesan", "balaji", "venky", “vetry","pavan");
// Correct
names.forEach(System.out::println);
Better way is library can supply a forEach method that applies a function to
each element
DEFAULT METHOD - INTRO
▪ Java collections library has been designed many years ago, and there is a problem.
▪ If the Collection interface gets new methods, such as forEach, then every program that
defines its own class implementing Collection will break
▪ That is simply unacceptable in Java, to support backward compatibility
Allowing interface methods with concrete implementations called
default methods
DEFAULT METHOD - INTRO
What happens if the exact same method is defined as a default method in one interface and
then again as a method of a superclass or another interface?
Rule #1
Classes win over
interfaces
Rule #2
More specific interfaces
win over less specific
ones
Rule #3
There’s no rule, If there is
not a unique winner
according to the above
rules
DEFAULT METHOD
interface Named {
default String getName() {
return “Named Interface”
}
}
interface Person {
long getId();
default String getName() {
return " Person Interface ";
}
}
class Student implements Person, Named {
...
}
getName
getName
Person, Named
DEFAULT METHOD
interface Named {
default String getName() {
return “Named Interface”
}
}
interface Person extends Named{
long getId();
default String getName() {
return " Person Interface ";
}
}
class Student implements Person, Named {
...
}
Named
getName
DEFAULT METHOD - MODIFIERS
▪ Visibility is fixed to public
▪ Keyword synchronized is forbidden
▪ Keyword final is forbidden
You are allowed to add static methods to interfaces
STATIC METHODS
Static methods cannot be inherited by the class implementing
Java SE 8
WHAT?
▪ Influenced by Joda-Time
▪ java.time package contains date, time, date/time, time zones, instants, duration, and
clocks manipulation.
▪ conforms to immutability, a lesson learnt from java.util.Calendar.
PROBLEMS - EXISTING DATE AND TIME APIS
▪ Bad Naming
▪ Historical Issues
▪ Design Problems
▪ Deficiencies
BAD NAMING
▪ Horrible naming decisions
▪ Date is not a date, it is an instant in time(Timestamp)
▪ Calendar is not a calendar, it is a date and time.
▪ Date is not a time
▪ The time field manipulation methods are deprecated
HISTORICAL ISSUES
▪ Date has no support for i18n or l10n
▪ Sun added IBM donated code
▪ Calendar
▪ TimeZone
▪ SimpleDateFormat
▪ Which don’t even play well together
▪ SimpleDateFormat can not be used to convert from or to Calendar
▪ And still kept months zero based
DESIGN PROBLEMS
▪ Date and Time objects are mutable
▪ In the core library, SimpleDateTime is:
▪ Instantiated in 225 places
▪ A field in 77 places
▪ A local variable in 103 places
▪ Which could be made much simpler with immutable objects
DEFICIENCIES
▪ How to represent common needs:
▪ My alarm clock rings at 6:00AM ( A time without date or timezone )
▪ I was born on March 23,1998 ( A date without time )
▪ My birthday is on March 23 ( A date without a year )
▪ This presentation is 180 minutes long ( a duration )
▪ A year has twelve months ( a period )
ONE SIMPLE EXAMPLE
▪ Using the current API
▪ Date chirstmas = new Date(2015,12,25);
▪ What date will this actually be?
▪ You would think 25th December,2015
▪ You would be wrong
▪ Actually, 25th January,3916
A BETTER WAY IS
JSR-310
SOME IMPORTANT CLASSES
▪ Clock
▪ LocalDate
▪ LocalTime
▪ LocalDateTime
▪ ZoneDateTime
▪ provides access to the current instant, date and time using a time-zone
▪ can be used instead of System.currentTimeMillis()
CLOCK
// Sample
final Clock clock = Clock.systemUTC();
System.out.println("INSTANT :" + clock.instant());
System.out.println("MILLIS :" + clock.millis());
OUTPUT:
INSTANT :2016-03-16T13:32:19.740Z
MILLIS :1458135139790
▪ LocaleDate - only the date part without a time-zone in the ISO-8601 calendar system
▪ LocaleDate could be created from Clock.
LOCALEDATE
// Sample
final LocalDate date = LocalDate.now();
final LocalDate dateFromClock = LocalDate.now(Clock.systemUTC());
System.out.println( "DATE : " + date );
System.out.println( "DATE FROM CLOCK : " + dateFromClock );
OUTPUT:
DATE : 2016-03-16
DATE FROM CLOCK : 2016-03-16
▪ LocaleTime - only the time part without a time-zone in the ISO-8601 calendar system
▪ LocaleTime could be created from Clock.
LOCALETIME
// Sample
final LocalTime time = LocalTime.now();
final LocalTime timeFromClock = LocalTime.now(Clock.systemUTC());
System.out.println( "TIME : " + time );
System.out.println( "TIME FROM CLOCK : " + timeFromClock );
OUTPUT:
TIME : 19:04:46.152
TIME FROM CLOCK : 13:34:46.152
▪ LocalDateTime - holds a date with time but without a time-zone in the ISO-8601
calendar system
LOCALDATETIME
// Sample
final LocalDateTime dateTime = LocalDateTime.now();
final LocalDateTime dateTimeFromClock = LocalDateTime.now(Clock.systemUTC());
System.out.println( "DATE TIME : " + dateTime );
System.out.println( "DATE TIME FROM CLOCK : " + dateTimeFromClock );
OUTPUT:
DATE TIME : 2016-03-16T19:05:53.556
DATE TIME FROM CLOCK : 2016-03-16T13:35:53.556
▪ ZonedDateTime - holds a date with time and with a time-zone in the ISO-8601
calendar system
ZONEDDATETIME
// Sample
final ZonedDateTime zonedDateTime =
ZonedDateTime.now();
final ZonedDateTime zonedDateTimeFromClock =
ZonedDateTime.now(Clock.systemUTC());
final ZonedDateTime zonedDateTimeFromZone =
ZonedDateTime.now( ZoneId.of("America/Los_Angeles"));
System.out.println( "ZONED DATE TIME : " +
zonedDateTime );
System.out.println( "ZONED DATE TIME FROM
CLOCK : " + zonedDateTimeFromClock );
System.out.println( "ZONED DATE TIME FROM ZONE
: " + zonedDateTimeFromZone );
OUTPUT:
ZONED DATE TIME : 2016-03-
16T19:06:34.761+05:30[Asia/Calcutta]
ZONED DATE TIME FROM CLOCK : 2016-03-16T13:36:34.761Z
ZONED DATE TIME FROM ZONE : 2016-03-16T06:36:34.761-
07:00[America/Los_Angeles]s
TIT BITS
▪ Class dependency analyzer: jdeps
▪ shows the package-level or class-level dependencies of Java class files
▪ jdeps XXX.jar
▪ Recursion Optimization:
▪ stack overflow problem
▪ tail-call optimization (TCO)
Java SE 8
STREAM INTRODUCTION
Old Way
final List<String> names = Arrays.asList("ganesan", "balaji", "venky", "Raju", "pavan");
for(int i = 0; i < names.size(); i++) {
System.out.println(friends.get(i));
}
for(String name : names) {
System.out.println(name);
}
names.forEach((final String name) -> System.out.println(name));
STREAM INTRODUCTION
Old Way
final List<String> names = Arrays.asList("ganesan", "balaji", "venky", "Raju", "pavan");
names.forEach(new Consumer<String>() {
public void accept(final String name) {
System.out.println(name);
}
});
names.forEach((name) -> System.out.println(name));
names.forEach(name -> System.out.println(name));
names.forEach(System.out::println);
STREAM INTRODUCTION
Old Way
long count = names.stream().filter(name -> name.startsWith("v")).count();
Old Way
final List<String> names = Arrays.asList("ganesan", "balaji", "venky", "Raju", "pavan");
Int totalCount = 0;
for (String name : names) {
if(name.startsWith("v")) {
totalCount++;
}
}
▪ Stream operations are either intermediate or terminal
▪ Most stream operations accept lambda expression
▪ Most of those operations must be both non-interfering and stateless
HOW STREAM WORK
final List<String> names = Arrays.asList("ganesan", "balaji", "venky", “vetry", "pavan");
names
.stream()
.filter(name -> name.startsWith(“v"))
.map(String::toUpperCase)
.sorted()
.forEach(System.out::println);
STREAM INTERMEDIATE OPERATION
• Return: Stream<T>
• Argument: Predicate<T, R>filter
• Return: Stream<T>
• Argument: Function<T, R>map
• Return: Stream<T>
• Argument:limit
• Return: Stream<T>
• Argument: Comparator<T>Sorted
• Return: Stream<T>
• Argument:Distinct
STREAM TERMINAL OPERATION
• Consume each element from a stream and applies a
lambda to each of them. The operations return void.forEach
• Return the number of elements in a stream. The
operation return longcount
• Reduce the stream to create collectioncollect
STREAM – FILTER
Stream exposes a filter method that takes in a Predicate to define
the filtering criteria
List<String> myList = Arrays.asList("a5", "b2", "c4", "d1", "e3");
myList
.stream()
.filter(s -> s.startWith(“a”))
.collect(Collectors.toList());
STREAM – FILTER
Streams support a method called distinct that returns
a stream with unique elements.
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()S
.filter(i -> i % 2 == 0)
.distinct()
.forEach(System.out::println);
STREAM – SKIP & LIMIT
Streams support a method called skip and limit
that returns a stream.
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
.filter(i -> i % 2 == 0)
.limit(3)
.forEach(System.out::println);
numbers.stream()
.filter(i -> i % 2 == 0)
.skip(3)
.forEach(System.out::println);
Old Way
for(String name : names) {
uppercaseNames.add(name.toUpperCase());
}
STREAM - MAP
Lamda Way
names.forEach(name -> uppercaseNames.add(name.toUpperCase()));
final List<String> names = Arrays.asList("ganesan", "balaji", "venky", “vetry","pavan");
final List<String> uppercaseNames = new ArrayList<String>();
STREAM - MAP
Streams support a method called map, which is used to
transform each element of the stream
final List<String> names = Arrays.asList("ganesan", "balaji", "venky", “vetry","pavan");
names.stream()
.map(name -> name.toUpperCase())
.collect(Collectors.toList());
STREAM – FIND & MATCH
Stream provides find the elements in a set of data match through the
allMatch, anyMatch, noneMatch, findFirst, and findAny methods
List<String> names = Arrays.asList("ganesan", "balaji", "venky", “vetry", "pavan");
names
.stream()
.anyMatch(s -> s.startsWith(“v"));
names
.stream()
.allMatch(s -> s.startsWith(“v"));
names
.stream()
. noneMatch(s -> s.startsWith(“v"));
Java SE 8
OPTIONAL
▪ Habitual way
String fullName = null;
System.out.println(fullName.toUpperCase());
if (fullName != null) {
System.out.println(fullName.toUpperCase());
}
OPTIONAL
▪ Tired of Null Pointer Exceptions? Consider Using Java SE 8's Optional API
▪ Make your code more readable and protect it against null pointer exceptions.
▪ Optional is just a container: it can hold a value of some type T or just be null.
▪ It provides a lot of useful methods so there is no need for explicit null checks.
OPTIONAL
▪ New way
Optional< String > fullName = Optional.ofNullable( null );
System.out.println( "Full Name is set? " + fullName.isPresent() );
System.out.println( "Full Name: " + fullName.orElseGet( () -> "Nothing" ) );
System.out.println( fullName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );
Output
Full Name is set? false
Full Name: Nothing
Hey Stranger!
OPTIONAL
▪ The isPresent() method returns true if this instance of Optional has non-null value and false
otherwise.
▪ The orElseGet() method provides the fallback mechanism in case Optional has null value by
accepting the function to generate the default one.
▪ The map() method transforms the current Optional’s value and returns the new Optional
instance.
▪ The orElse() method is similar to orElseGet() but instead of function it accepts the default
value.
OPTIONAL
▪ New way
Optional< String > firstName = Optional.of( "Tom" );
System.out.println( "First Name is set? " + firstName.isPresent() );
System.out.println( "First Name: " + firstName.orElseGet( () -> "[none]" ) );
System.out.println( firstName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );
firstName.ifPresent( fname -> {System.out.println(fname.toUpperCase());});
System.out.println();
There is also another useful method ifPresent which execute actions directly when the value
is present, in combination with Lambdas
Output
First Name is set? true
First Name: Tom
Hey Tom!
TOM
Old Way
for(String name : names) {
int sum = 0;
for (int x : numbers) {
sum += x;
}
STREAM - REDUCE
List<Integer> numbers = Arrays.asList(4, 5, 3, 9);
STREAM - REDUCE
List<Integer> numbers = Arrays.asList(4, 5, 3, 9);
▪ An initial value, here 0
▪ A BinaryOperator<T> to combine two
elements and produce a new value
▪ Here you use the lambda (a, b) -> a + b
numbers.stream()
.reduce(0, (a, b) -> a + b);
▪ Streams can be either sequential or parallel
▪ Operations on sequential streams are performed on a single thread
▪ Operations on parallel streams are performed concurrent
STREAM – PARALLEL
Parallel Stream
int sum = numbers.parallelStream().reduce(0, (a, b) -> a + b);
▪ Creating and using a collector with the Collectors
▪ Reducing streams of data to a single value
▪ Grouping and partitioning data
STREAM – COLLECTOR INTRO
Collector applies a transforming function to the element and
accumulates the result in a data structure that forms the final output
Map<String, List<Transaction>> transactionByChannel = new HashMap();
for(Transaction trans : transactions) {
List<Transaction> transactionList =
transactionByChannel.get(trans.getChannel());
if(transactionList == null) {
transactionList = new ArrayList<>();
transactionByChannel.put(trans.getChannel(), transactionList);
}
transactionList.add(trans);
}
STREAM – COLLECTOR INTRO
Create the
map where
the grouped
Transaction
will be
accumulated
Iterate the list
of transaction
If there is no entry in the
grouping map for this
Channel create it
Add the currently
traversed
transaction to the
list of transactions
with the same
channel
STREAM – COLLECTOR INTRO
Map<String, List<Transaction>> transactionsByChennal =
transactions.stream()
.collect( Collectors.groupingBy(Transaction::getChannel) );Collectors.groupingBy(Transaction::getChannel)
▪ Summarizing elements
▪ Grouping elements
▪ Partitioning elements
STREAM – COLLECTOR INTRO
STREAM – SUMMARIZATION
List<Integer> numbers = Arrays.asList(2,4,1,8,3,7);
IntSummaryStatistics statistics =
numbers.stream().collect( Collectors.summarizingInt(num -> num) );Collectors.summarizingInt(num -> num)
Summary
Sum
25
Min
1
Average
4.16
Max
8
Count
6
IntSummaryStatistics {
count=6,
sum=25,
min=1,
average=4.166667,
max=8
}
STREAM – GROUPING
Map<String, List<Transaction>> transactionsByChennal =
transactions.stream()
.collect( Collectors.groupingBy(Transaction::getChannel) );Collectors.groupingBy(Transaction::getChannel)
STREAM – GROUPING
final List<String> values = Arrays.asList(“a", “d”, “A”, “b”, “d”);
Map<String, Long> count =
values.stream()
.collect( Collectors.groupingBy(String :: toLowerCase,
Collectors.counting));
String :: toLowerCase,
Transforming function
Aggregate function
Collectors.counting
{a=2, b=1, d=2}
STRINGS AND COMPARATORS
▪ String
▪ new chars method
▪ chars method returns a Stream
▪ Hence map, filter, reduce Stream methods are leveraged to process
final String str = “w00t”;
str.chars().mapToObj(x-> Character.valueOf((char)x)).forEach(System.out::println);
// Only Digits are filtered to print.
str.chars().filter(Character::isDigit).mapToObj(x->
Character.valueOf((char)x)).forEach(System.out::println);
STRINGS AND COMPARATORS
▪ Method references
▪ String::toUppercase and Character::isDigit
▪ Both Instance and static methods can be referenced
▪ Caveat -> Double::toString
▪ Double has one instance toString() and one static toString()
COMPARATOR INTERFACE
▪ Became functional interface J8.
▪ Hence Lambda compatible.
COMPARATOR SAMPLE
public class Person {
private final String name;
private final int age;
public Person(final String theName, final int theAge) {
name = theName;
age = theAge;
}
public String getName() { return name; }
public int getAge() { return age; }
public int ageDifference(final Person other) {
return age - other.age;
}}
COMPARATOR.REVERSED()
▪ Has a new method reversed();
▪ Which can be used to reverse the comparator function.
Comparator<Person> ascendingComparator = (x,y) -> x.ageDifference(y);
Comparator<Person> decendingComparator = ascendingComparator.reversed();
MULTIPLE AND FLUENT COMPARISONS
▪ Comparator.comparing
▪ Comparator.thenComparing
final Function<Person,Integer> byAge = x -> x.getAge();
final Function<Person,String> byName = x -> x.getName();
ascendingPersons = persons.stream().sorted(comparing(byAge).thenComparing(byName)).collect(toList());
ascendingPersons.forEach(System.out::println);
COLLECT METHOD AND COLLECTOR CLASS
▪ The collect method takes a stream of elements and collects or gathers them into a
result container. To do that, the method needs to know three things:
▪ How to make a result container (for example, using the ArrayList::new method)
▪ How to add a single element to a result container (for example, using the ArrayList::add
method)
▪ How to merge one result container into another (for example, using the ArrayList::addAll
method)
COLLECTOR CONVENIENT METHODS
▪ toList();
▪ toSet();
▪ toMap();
▪ In Java we often execute code eagerly
▪ There are situations we create heavy weight objects only at the moment needed. The delayed object creation is mainly
meant for performance reasons
LAZY INITIALIZATION
Habitual Way
public class Heavy {
public Heavy() {
System.out.println("Heavy created");
}
public String toString() {
return "Quite heavy";
}
}
// Lets use an instance of this class in another Holder class named HolderNaive
public class HolderNaive {
private Heavy heavy;
public HolderNaive() {
System.out.println("Holder Naive created");
}
public Heavy getHeavy() {
if(heavy == null) {
heavy = new Heavy();
}
return heavy;
}
}
Habitual Way
final HolderNaive holder = new HolderNaive();
System.out.println("Deferring heavy creation");
System.out.println(holder.getHeavy());
System.out.println(holder.getHeavy());
output:
Holder created
Deferring heavy creation
Heavy created
Quite heavy
Quite heavy
LAZY INITIALIZATION
▪ The above solution is simple but it fails to provide thread safety.
LAZY INITIALIZATION
Habitual Way
// Providing thread safety
public synchronized Heavy getHeavy() {
if(heavy == null) {
heavy = new Heavy();
}
return heavy;
}
▪ The above solution is quite heavy because every call to the method is synchronized.
▪ We need thread safety until the reference is first created and then onwards unhindered access is
needed
LAZY INITIALIZATION
New Way
public class HolderNaive {
private Supplier<Heavy> heavy = () -> new Heavy();
public HolderNaive() {
System.out.println("Holder Naive created");
}
public Heavy getHeavy() {
heavy.get();
}
}
▪ We can simplify the delayed object creation using the functional interface Supplier<T> which has
an abstract method get() that returns an instance.
▪ In other words Supplier<T> is a factory
Java SE 8
NASHORN
▪ Until Java SE 7, JDKs shipped with a JavaScript scripting engine based on Mozilla Rhino
▪ SE 8 will instead ship with a new engine called Oracle Nashorn
▪ Based on JSR-292 and invokedynamic.
▪ ECMA-compliant JavaScript, currently supports ECMAScript 5.1
▪ Objects available for Web browsers are not available. For example, console, window
TO USE
1. jjs command-line tool[REPL]
2. Oracle Nashorn as an embedded scripting engine inside Java
3. Using Java inside JS
JJS REPL
var hello = function() {
print("Hello Nashorn!");
};
hello();
INVOKING JAVASCRIPT FUNCTIONS FROM JAVA
▪ Direct Reference
ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine = engineManager.getEngineByName("nashorn");
engine.eval("function hello(name) { print("Hello " + name +
"!");};");
System.out.println(engine.eval("hello("Banca Sella");"));
▪ File Reference
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine =
scriptEngineManager.getEngineByName("nashorn");
scriptEngine.eval(new
FileReader("C:/Users/gbs02362/workspace/J8/src/it/sella/dsn/training/j8/nashorn/he
llo.js"));
Invocable invocable = (Invocable) scriptEngine;
invocable.invokeFunction("hello", "Banca Sella");
invocable.invokeFunction("helloObject", LocalDateTime.now());
INVOKING JAVA METHODS FROM JAVASCRIPT
▪ Java.type
var ArrayList = Java.type('java.util.ArrayList');
var list = new ArrayList();
list.add('a');
list.add('b');
list.add('c');
for each (var el in list) print(el);
INVOKING JAVA METHODS FROM JAVASCRIPT
▪ Without Java.type
var map = new java.util.HashMap();
map.put('foo', 'val1');
map.put('bar', 'val2');
for each (var e in map.keySet()) print(e); // foo, bar
for each (var e in map.values()) print(e); // val1, val2
INVOKING JAVA METHODS FROM JAVASCRIPT
▪ Lambda leveraged
var employeeList = new java.util.ArrayList();
employeeList.add("John");
employeeList.add("Joy");
employeeList.add("Krish");
employeeList.add("Kannan");
employeeList.add("Joe");
employeeList.add("Arul");
employeeList.add("Ravi");
employeeList.add("Shiva");
LAMBDA LEVERAGED…..
employeeList.stream()
.filter(function(el) {
return el.startsWith("J");
})
.sorted()
.forEach(function(el) {
print(el);
});

More Related Content

PDF
The... Wonderful? World of Lambdas
PPTX
Java gets a closure
PDF
Java 8 Lambda Built-in Functional Interfaces
PPTX
Functions
PDF
Refactoring to Java 8 (Devoxx BE)
PDF
Pragmatic functional refactoring with java 8
PDF
Scala is java8.next()
PDF
The Ring programming language version 1.5.3 book - Part 32 of 184
The... Wonderful? World of Lambdas
Java gets a closure
Java 8 Lambda Built-in Functional Interfaces
Functions
Refactoring to Java 8 (Devoxx BE)
Pragmatic functional refactoring with java 8
Scala is java8.next()
The Ring programming language version 1.5.3 book - Part 32 of 184

What's hot (20)

PDF
Java 8: the good parts!
PDF
Java Class Design
PDF
Functional Programming in Java 8 - Exploiting Lambdas
PDF
Java 8 Lambda Expressions
PDF
Java 8 lambda expressions
PDF
Java 8 Workshop
PDF
Java 8 - project lambda
PDF
The Ring programming language version 1.4.1 book - Part 9 of 31
PPTX
Linq and lambda
PDF
Thumbtack Expertise Days # 5 - Javaz
PDF
Dynamic websites lec3
PDF
Functional Java 8 in everyday life
PDF
The Ring programming language version 1.9 book - Part 124 of 210
PDF
PPTX
Use of Apache Commons and Utilities
PDF
Procedure Typing for Scala
PPTX
Pattern Matching in Java 14
ODP
Functional Objects & Function and Closures
PPT
PLSQL Cursors
PDF
Creating Lazy stream in CSharp
Java 8: the good parts!
Java Class Design
Functional Programming in Java 8 - Exploiting Lambdas
Java 8 Lambda Expressions
Java 8 lambda expressions
Java 8 Workshop
Java 8 - project lambda
The Ring programming language version 1.4.1 book - Part 9 of 31
Linq and lambda
Thumbtack Expertise Days # 5 - Javaz
Dynamic websites lec3
Functional Java 8 in everyday life
The Ring programming language version 1.9 book - Part 124 of 210
Use of Apache Commons and Utilities
Procedure Typing for Scala
Pattern Matching in Java 14
Functional Objects & Function and Closures
PLSQL Cursors
Creating Lazy stream in CSharp
Ad

Viewers also liked (12)

PPTX
Byte array to hex string transformer
PDF
5 2. string processing
PDF
Design, Simulation and Verification of Generalized Photovoltaic cells Model U...
PPT
Strings Arrays
PPTX
Control flow statements in java
PPTX
TypeScript by Howard
PDF
Multi string PV array
PDF
Java 8 new features or the ones you might actually use
PPTX
자바로 배우는 자료구조
PDF
프로그래머가 알아야 하는 메모리 관리 기법
PPTX
Arrays in java
Byte array to hex string transformer
5 2. string processing
Design, Simulation and Verification of Generalized Photovoltaic cells Model U...
Strings Arrays
Control flow statements in java
TypeScript by Howard
Multi string PV array
Java 8 new features or the ones you might actually use
자바로 배우는 자료구조
프로그래머가 알아야 하는 메모리 관리 기법
Arrays in java
Ad

Similar to Java SE 8 (20)

PPTX
Java 8 new features
PPT
Major Java 8 features
PDF
Java 8 by example!
PPTX
Java 8 features
PPTX
Java 8 lambdas expressions
PPTX
Functional programming with_jdk8-s_ritter
PDF
Java 8 features
PDF
FP in Java - Project Lambda and beyond
PDF
Lambdas & Streams
PPTX
JDK8 Lambdas and Streams: Changing The Way You Think When Developing Java
PDF
Java 8
PDF
Productive Programming in Java 8 - with Lambdas and Streams
PPTX
Functional Programming With Lambdas and Streams in JDK8
PPTX
Project Lambda: Evolution of Java
PPTX
Java 8 Feature Preview
PDF
Functional Thinking - Programming with Lambdas in Java 8
PDF
Lambda Functions in Java 8
PPTX
Lambdas and-streams-s ritter-v3
PPTX
PDF
Java 8 new features
Major Java 8 features
Java 8 by example!
Java 8 features
Java 8 lambdas expressions
Functional programming with_jdk8-s_ritter
Java 8 features
FP in Java - Project Lambda and beyond
Lambdas & Streams
JDK8 Lambdas and Streams: Changing The Way You Think When Developing Java
Java 8
Productive Programming in Java 8 - with Lambdas and Streams
Functional Programming With Lambdas and Streams in JDK8
Project Lambda: Evolution of Java
Java 8 Feature Preview
Functional Thinking - Programming with Lambdas in Java 8
Lambda Functions in Java 8
Lambdas and-streams-s ritter-v3

Recently uploaded (20)

DOCX
How to Use SharePoint as an ISO-Compliant Document Management System
PPTX
Why Generative AI is the Future of Content, Code & Creativity?
PDF
Time Tracking Features That Teams and Organizations Actually Need
PDF
EaseUS PDF Editor Pro 6.2.0.2 Crack with License Key 2025
PDF
Wondershare Recoverit Full Crack New Version (Latest 2025)
PPTX
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
PDF
Types of Token_ From Utility to Security.pdf
PDF
Autodesk AutoCAD Crack Free Download 2025
PPTX
Computer Software and OS of computer science of grade 11.pptx
PDF
Website Design Services for Small Businesses.pdf
PDF
iTop VPN Crack Latest Version Full Key 2025
PDF
Topaz Photo AI Crack New Download (Latest 2025)
PPTX
Advanced SystemCare Ultimate Crack + Portable (2025)
PDF
Designing Intelligence for the Shop Floor.pdf
PDF
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
PPTX
Tech Workshop Escape Room Tech Workshop
PPTX
Computer Software - Technology and Livelihood Education
PPTX
WiFi Honeypot Detecscfddssdffsedfseztor.pptx
PDF
AI/ML Infra Meetup | LLM Agents and Implementation Challenges
PPTX
CNN LeNet5 Architecture: Neural Networks
How to Use SharePoint as an ISO-Compliant Document Management System
Why Generative AI is the Future of Content, Code & Creativity?
Time Tracking Features That Teams and Organizations Actually Need
EaseUS PDF Editor Pro 6.2.0.2 Crack with License Key 2025
Wondershare Recoverit Full Crack New Version (Latest 2025)
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
Types of Token_ From Utility to Security.pdf
Autodesk AutoCAD Crack Free Download 2025
Computer Software and OS of computer science of grade 11.pptx
Website Design Services for Small Businesses.pdf
iTop VPN Crack Latest Version Full Key 2025
Topaz Photo AI Crack New Download (Latest 2025)
Advanced SystemCare Ultimate Crack + Portable (2025)
Designing Intelligence for the Shop Floor.pdf
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
Tech Workshop Escape Room Tech Workshop
Computer Software - Technology and Livelihood Education
WiFi Honeypot Detecscfddssdffsedfseztor.pptx
AI/ML Infra Meetup | LLM Agents and Implementation Challenges
CNN LeNet5 Architecture: Neural Networks

Java SE 8

  • 1. Deep Dive JAVA SE 8 AND JAVA EE 7
  • 3. BEST PRACTICE A method or technique that has consistently shown results superior to those achieved with other means
  • 4. WHAT ARE WE GOING TO TASTE
  • 6. LAMBDA EXPRESSIONS ▪ Anonymous methods ▪ Function ▪ Passed around ▪ Concise A block of code that you can pass around so it can be executed later, once or multiple times
  • 7. INTRODUCTION TO LAMBDA Old Way List<String> names = Arrays.asList("peter", "anna", "mike", "xenia"); class NameComparator implements Comparator<String> { @Override public int compare(final String name, final String anotherName) { return name.compareTo(anotherName); } } Collections.sort(names, new NameComparator());
  • 8. INTRODUCTION TO LAMBDA Better Way List<String> names = Arrays.asList("peter", "anna", "mike", "xenia"); Collections.sort(names, new Comparator<String>() { @Override public int compare(final String name, final String anotherName) { return name.compareTo(anotherName); } });
  • 9. Lambda Way List<String> names = Arrays.asList("peter", "anna", "mike", "xenia"); Collections.sort(names,(String a, String b) -> { return a.compareTo(b);} ); INTRODUCTION TO LAMBDA (String a, String b) -> { return a.compareTo(b);} (arguments) -> {body}
  • 10. LAMBDA EXAMPLE Write it like a method (String first, String second) -> { if (first.length() < second.length()) return -1; else if (first.length() > second.length()) return 1; else return 0; } Even without param () -> { for (int i = 0; i < 1000; i++) doWork(); }
  • 11. ▪ Make use of parameter type inference ▪ Only specify the types when compiler needs it ▪ Do not use parameter brackets when optional LAMBDA – TYPE INFERENCE // Avoid Comparator<String> comp = (String a, String b) -> a.compareTo(b); (Integer t) -> System.out.println(t); // Prefer Comparator<String> comp = (a, b) -> a.compareTo(b); t -> System.out.println(t);
  • 12. ▪ Lambda expression to return a value in all branch ▪ Not allowed to return a value in some branches LAMBDA – RETURN CONDITION // Prefer (int x) -> { if (x >= 0) return 1; else return 0; } // Error (int x) -> { if (x >= 0) return 1; }
  • 13. ▪ A block of code and Parameters ▪ Values for the free variables LAMBDA – VARIABLE SCOPE public static void repeatMessage( String text, int count ) { Runnable r = () -> { for (int i = 0; i < count ; i++) { System.out.println( text ); } }; new Thread(r).start(); } free variable String text, int count text count
  • 14. ▪ Do not declare local variables as final ▪ Use new “effectively final” concept LAMBDA – VARIABLE SCOPE public static void orderByName( List<String> names ) { int first = 0; Comparator<String> comp = (first, second) -> first.compareTo(second); Collections.sort(names, comp); } Effective finalList<String> names names,
  • 15. LAMBDA – VARIABLE SCOPE for (int i = 0; i < n; i++) { new Thread(() -> System.out.println( i )).start(); // Error—cannot capture i } ▪ Reference variables value is not allowed to change ▪ Parameters are effective final for (String arg : args) { new Thread(() -> System.out.println( arg )).start(); } Reference variable is not fixed i i Effective final arg arg
  • 16. ▪ Lambda expression can not mutate LAMBDA – VARIABLE SCOPE public class LambdaNonFinalExample { static boolean odd = false; public static void main(String[] args) throws Exception { runLambda(() -> odd = true); System.out.println("Odd=" + odd); } public static void runLambda(Callable c) throws Exception { c.call(); } } Not possible to mutate boolean odd = false; runLambda(() -> odd = true);
  • 17. LAMBDA – EXCEPTION HANDLING public Supplier<?> createInstance(final String className) { return () -> { Class.forName(className).newInstance() }; } Functional interfaces not allowed for a checked exception to be thrown Class.forName(className).newInstance()
  • 18. ▪ Catch the exception inside the lambda expression LAMBDA – EXCEPTION HANDLING public Supplier<?> createInstance(final String className) { return () -> { try { return Class.forName(className).newInstance(); } catch( ClassNotFoundException | IllegalAccessException | InstantiationException e ) { throw new RuntimeException(e); } }; } try { return Class.forName(className).newInstance(); } catch( ClassNotFoundException | IllegalAccessException | InstantiationException e ) { throw new RuntimeException(e); }
  • 19. ▪ Handle the exception using Consumer LAMBDA – EXCEPTION HANDLING Better Way public Supplier<?> createInstance(final String className, final Consumer<? super Throwable> consumer ) { return () -> { try { return Class.forName(className).newInstance(); } catch( ClassNotFoundException | IllegalAccessException | InstantiationException e ) { consumer.accept(e); return null; } }; } Consumer<? super Throwable> consumer consumer.accept(e);
  • 21. FUNCTIONAL INTERFACE ▪ An Interface with a single abstract method ▪ Runnable ▪ Comparable ▪ Callable ▪ Java SE 8 new functional interfaces ▪ Function<T,R> ▪ Predicate<T> ▪ Supplier<T> ▪ Consumer<T>
  • 22. FUNCTIONAL INTERFACES An interface which has Single Abstract Method ▪ Functional interface must have a single abstract method ▪ Supply a lambda whenever an object of an interface with a single abstract method ▪ Tag any functional interface with the @FunctionalInterface annotation
  • 23. FUNCTION Purpose is to return any result by working on a single input argument ▪ It accepts an argument of type T ▪ Returns a result of type R ▪ Applying specified logic on the input via the apply method
  • 24. FUNCTION Function<String, Integer> stringToInt = x -> Integer.valueOf(x); stringToInt.apply("4"); @FunctionalInterface public interface Function<T, R> { R apply(T t); } Output 4
  • 25. PREDICATE Function for checking a condition ▪ Accepting a single argument to evaluate to a boolean result ▪ It has a single method test which returns the boolean value
  • 26. FUNCTION Predicate<String> emptyStringChecker = s -> s.isEmpty(); emptyStringChecker.test(“JAVA8"); @FunctionalInterface public interface Predicate<T> { boolean test(T t); } Output false
  • 27. CONSUMER Perform operations on the arguments ▪ Accepts a single argument but does not return any result ▪ Used to perform operations on the arguments ▪ Persisting ▪ Invoking house keeping operations ▪ Emailing ▪ Etc..
  • 28. CONSUMER @FunctionalInterface public interface Consumer<T> { void accept(T t); } final List<String> names = Arrays.asList("ganesan", "balaji", "venky", "Raju", "pavan"); names.forEach(new Consumer<String>() { public void accept(final String name) { System.out.println(name); } });
  • 29. SUPPLIER Supplies us with a result ▪ Accepts a single argument but does not return any result ▪ Used to fetching values ▪ Configuration values from database ▪ Loading with reference data ▪ Creating an list of data with default identifiers ▪ Etc..
  • 31. FUNCTIONAL INTERFACES Function that expects two arguments but produces a result by operating on these two arguments ▪ BiPredicate ▪ BiConsumer ▪ BiFunction
  • 32. DECLARING OWN FUNCTIONAL INTERFACE We can declare our own Functional Interface by defining Single Abstract Method in interface ▪ Can tag any functional interface with @FunctionalInterface ▪ Compiler checks entity is an interface with a single abstract method ▪ Javadoc page includes a statement that your interface is a functional interface
  • 33. ▪ It is not required to use the annotation ▪ Any interface with a single abstract method is, by definition, a functional interface ▪ Using the @FunctionalInterface annotation is a good idea. DECLARING OWN FUNCTIONAL INTERFACE // Not Correct @FunctionalInterface public interface FunctionalInterfaceTest{ void display(); void anotherDisplay(); } // Correct @FunctionalInterface public interface FunctionalInterfaceTest{ void display(); }
  • 34. AVOID METHOD OVERLOAD ▪ Lambdas use target typing ▪ Clashes with method overloading // avoid public class Foo<T> { public Foo<R> apply(Function<T, R> fn); public Foo<T> apply(UnaryOperator<T> fn); }
  • 35. AVOID METHOD OVERLOAD ▪ Lambdas use target typing ▪ Clashes with method overloading ▪ Use different method names to avoid clashes // prefer public class Foo<T> { public Foo<R> applyFunction(Function<T, R> fn); public Foo<T> applyOperator(UnaryOperator<T> fn); }
  • 36. METHOD REFERENCE Accept reference to a method where an implementation of a functional interface is expected (String s) -> System.out.println(s) System.out::println Where :: signifies that System.out'svoid println(String s) method is being referenced
  • 37. METHOD REFERENCE ▪ Reference to a static method ▪ className::staticMethodName ▪ Reference to an instance method of a particular object ▪ objectName::instanceMethodName ▪ Reference to an instance method of an arbitrary object of a particular type ▪ className::instanceMethodName ▪ Reference to a constructor ▪ className::new. className
  • 38. METHOD REFERENCE class ComparisonProvider { public int compareByName(Person a, Person b) { return a.getName().compareTo(b.getName()); } public int compareByAge(Person a, Person b) { return a.getBirthday().compareTo(b.getBirthday()); } } ComparisonProvider myComparisonProvider = new ComparisonProvider(); Arrays.sort(rosterAsArray, myComparisonProvider::compareByName );myComparisonProvider::compareByName compareByName
  • 39. METHOD REFERENCE String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert"}; Arrays.sort(stringArray, String::compareToIgnoreCase);String::compareToIgnoreCase
  • 40. Many languages integrate function expressions with their collections library DEFAULT METHOD - INTRO Old Way for (int i = 0; i < names.size(); i++) { System.out.println(list.get(i)); } final List<String> names = Arrays.asList("ganesan", "balaji", "venky", “vetry","pavan"); // Correct names.forEach(System.out::println); Better way is library can supply a forEach method that applies a function to each element
  • 41. DEFAULT METHOD - INTRO ▪ Java collections library has been designed many years ago, and there is a problem. ▪ If the Collection interface gets new methods, such as forEach, then every program that defines its own class implementing Collection will break ▪ That is simply unacceptable in Java, to support backward compatibility Allowing interface methods with concrete implementations called default methods
  • 42. DEFAULT METHOD - INTRO What happens if the exact same method is defined as a default method in one interface and then again as a method of a superclass or another interface? Rule #1 Classes win over interfaces Rule #2 More specific interfaces win over less specific ones Rule #3 There’s no rule, If there is not a unique winner according to the above rules
  • 43. DEFAULT METHOD interface Named { default String getName() { return “Named Interface” } } interface Person { long getId(); default String getName() { return " Person Interface "; } } class Student implements Person, Named { ... } getName getName Person, Named
  • 44. DEFAULT METHOD interface Named { default String getName() { return “Named Interface” } } interface Person extends Named{ long getId(); default String getName() { return " Person Interface "; } } class Student implements Person, Named { ... } Named getName
  • 45. DEFAULT METHOD - MODIFIERS ▪ Visibility is fixed to public ▪ Keyword synchronized is forbidden ▪ Keyword final is forbidden You are allowed to add static methods to interfaces
  • 46. STATIC METHODS Static methods cannot be inherited by the class implementing
  • 48. WHAT? ▪ Influenced by Joda-Time ▪ java.time package contains date, time, date/time, time zones, instants, duration, and clocks manipulation. ▪ conforms to immutability, a lesson learnt from java.util.Calendar.
  • 49. PROBLEMS - EXISTING DATE AND TIME APIS ▪ Bad Naming ▪ Historical Issues ▪ Design Problems ▪ Deficiencies
  • 50. BAD NAMING ▪ Horrible naming decisions ▪ Date is not a date, it is an instant in time(Timestamp) ▪ Calendar is not a calendar, it is a date and time. ▪ Date is not a time ▪ The time field manipulation methods are deprecated
  • 51. HISTORICAL ISSUES ▪ Date has no support for i18n or l10n ▪ Sun added IBM donated code ▪ Calendar ▪ TimeZone ▪ SimpleDateFormat ▪ Which don’t even play well together ▪ SimpleDateFormat can not be used to convert from or to Calendar ▪ And still kept months zero based
  • 52. DESIGN PROBLEMS ▪ Date and Time objects are mutable ▪ In the core library, SimpleDateTime is: ▪ Instantiated in 225 places ▪ A field in 77 places ▪ A local variable in 103 places ▪ Which could be made much simpler with immutable objects
  • 53. DEFICIENCIES ▪ How to represent common needs: ▪ My alarm clock rings at 6:00AM ( A time without date or timezone ) ▪ I was born on March 23,1998 ( A date without time ) ▪ My birthday is on March 23 ( A date without a year ) ▪ This presentation is 180 minutes long ( a duration ) ▪ A year has twelve months ( a period )
  • 54. ONE SIMPLE EXAMPLE ▪ Using the current API ▪ Date chirstmas = new Date(2015,12,25); ▪ What date will this actually be? ▪ You would think 25th December,2015 ▪ You would be wrong ▪ Actually, 25th January,3916
  • 55. A BETTER WAY IS JSR-310
  • 56. SOME IMPORTANT CLASSES ▪ Clock ▪ LocalDate ▪ LocalTime ▪ LocalDateTime ▪ ZoneDateTime
  • 57. ▪ provides access to the current instant, date and time using a time-zone ▪ can be used instead of System.currentTimeMillis() CLOCK // Sample final Clock clock = Clock.systemUTC(); System.out.println("INSTANT :" + clock.instant()); System.out.println("MILLIS :" + clock.millis()); OUTPUT: INSTANT :2016-03-16T13:32:19.740Z MILLIS :1458135139790
  • 58. ▪ LocaleDate - only the date part without a time-zone in the ISO-8601 calendar system ▪ LocaleDate could be created from Clock. LOCALEDATE // Sample final LocalDate date = LocalDate.now(); final LocalDate dateFromClock = LocalDate.now(Clock.systemUTC()); System.out.println( "DATE : " + date ); System.out.println( "DATE FROM CLOCK : " + dateFromClock ); OUTPUT: DATE : 2016-03-16 DATE FROM CLOCK : 2016-03-16
  • 59. ▪ LocaleTime - only the time part without a time-zone in the ISO-8601 calendar system ▪ LocaleTime could be created from Clock. LOCALETIME // Sample final LocalTime time = LocalTime.now(); final LocalTime timeFromClock = LocalTime.now(Clock.systemUTC()); System.out.println( "TIME : " + time ); System.out.println( "TIME FROM CLOCK : " + timeFromClock ); OUTPUT: TIME : 19:04:46.152 TIME FROM CLOCK : 13:34:46.152
  • 60. ▪ LocalDateTime - holds a date with time but without a time-zone in the ISO-8601 calendar system LOCALDATETIME // Sample final LocalDateTime dateTime = LocalDateTime.now(); final LocalDateTime dateTimeFromClock = LocalDateTime.now(Clock.systemUTC()); System.out.println( "DATE TIME : " + dateTime ); System.out.println( "DATE TIME FROM CLOCK : " + dateTimeFromClock ); OUTPUT: DATE TIME : 2016-03-16T19:05:53.556 DATE TIME FROM CLOCK : 2016-03-16T13:35:53.556
  • 61. ▪ ZonedDateTime - holds a date with time and with a time-zone in the ISO-8601 calendar system ZONEDDATETIME // Sample final ZonedDateTime zonedDateTime = ZonedDateTime.now(); final ZonedDateTime zonedDateTimeFromClock = ZonedDateTime.now(Clock.systemUTC()); final ZonedDateTime zonedDateTimeFromZone = ZonedDateTime.now( ZoneId.of("America/Los_Angeles")); System.out.println( "ZONED DATE TIME : " + zonedDateTime ); System.out.println( "ZONED DATE TIME FROM CLOCK : " + zonedDateTimeFromClock ); System.out.println( "ZONED DATE TIME FROM ZONE : " + zonedDateTimeFromZone ); OUTPUT: ZONED DATE TIME : 2016-03- 16T19:06:34.761+05:30[Asia/Calcutta] ZONED DATE TIME FROM CLOCK : 2016-03-16T13:36:34.761Z ZONED DATE TIME FROM ZONE : 2016-03-16T06:36:34.761- 07:00[America/Los_Angeles]s
  • 62. TIT BITS ▪ Class dependency analyzer: jdeps ▪ shows the package-level or class-level dependencies of Java class files ▪ jdeps XXX.jar ▪ Recursion Optimization: ▪ stack overflow problem ▪ tail-call optimization (TCO)
  • 64. STREAM INTRODUCTION Old Way final List<String> names = Arrays.asList("ganesan", "balaji", "venky", "Raju", "pavan"); for(int i = 0; i < names.size(); i++) { System.out.println(friends.get(i)); } for(String name : names) { System.out.println(name); }
  • 65. names.forEach((final String name) -> System.out.println(name)); STREAM INTRODUCTION Old Way final List<String> names = Arrays.asList("ganesan", "balaji", "venky", "Raju", "pavan"); names.forEach(new Consumer<String>() { public void accept(final String name) { System.out.println(name); } }); names.forEach((name) -> System.out.println(name)); names.forEach(name -> System.out.println(name)); names.forEach(System.out::println);
  • 66. STREAM INTRODUCTION Old Way long count = names.stream().filter(name -> name.startsWith("v")).count(); Old Way final List<String> names = Arrays.asList("ganesan", "balaji", "venky", "Raju", "pavan"); Int totalCount = 0; for (String name : names) { if(name.startsWith("v")) { totalCount++; } }
  • 67. ▪ Stream operations are either intermediate or terminal ▪ Most stream operations accept lambda expression ▪ Most of those operations must be both non-interfering and stateless HOW STREAM WORK final List<String> names = Arrays.asList("ganesan", "balaji", "venky", “vetry", "pavan"); names .stream() .filter(name -> name.startsWith(“v")) .map(String::toUpperCase) .sorted() .forEach(System.out::println);
  • 68. STREAM INTERMEDIATE OPERATION • Return: Stream<T> • Argument: Predicate<T, R>filter • Return: Stream<T> • Argument: Function<T, R>map • Return: Stream<T> • Argument:limit • Return: Stream<T> • Argument: Comparator<T>Sorted • Return: Stream<T> • Argument:Distinct
  • 69. STREAM TERMINAL OPERATION • Consume each element from a stream and applies a lambda to each of them. The operations return void.forEach • Return the number of elements in a stream. The operation return longcount • Reduce the stream to create collectioncollect
  • 70. STREAM – FILTER Stream exposes a filter method that takes in a Predicate to define the filtering criteria List<String> myList = Arrays.asList("a5", "b2", "c4", "d1", "e3"); myList .stream() .filter(s -> s.startWith(“a”)) .collect(Collectors.toList());
  • 71. STREAM – FILTER Streams support a method called distinct that returns a stream with unique elements. List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4); numbers.stream()S .filter(i -> i % 2 == 0) .distinct() .forEach(System.out::println);
  • 72. STREAM – SKIP & LIMIT Streams support a method called skip and limit that returns a stream. List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4); numbers.stream() .filter(i -> i % 2 == 0) .limit(3) .forEach(System.out::println); numbers.stream() .filter(i -> i % 2 == 0) .skip(3) .forEach(System.out::println);
  • 73. Old Way for(String name : names) { uppercaseNames.add(name.toUpperCase()); } STREAM - MAP Lamda Way names.forEach(name -> uppercaseNames.add(name.toUpperCase())); final List<String> names = Arrays.asList("ganesan", "balaji", "venky", “vetry","pavan"); final List<String> uppercaseNames = new ArrayList<String>();
  • 74. STREAM - MAP Streams support a method called map, which is used to transform each element of the stream final List<String> names = Arrays.asList("ganesan", "balaji", "venky", “vetry","pavan"); names.stream() .map(name -> name.toUpperCase()) .collect(Collectors.toList());
  • 75. STREAM – FIND & MATCH Stream provides find the elements in a set of data match through the allMatch, anyMatch, noneMatch, findFirst, and findAny methods List<String> names = Arrays.asList("ganesan", "balaji", "venky", “vetry", "pavan"); names .stream() .anyMatch(s -> s.startsWith(“v")); names .stream() .allMatch(s -> s.startsWith(“v")); names .stream() . noneMatch(s -> s.startsWith(“v"));
  • 77. OPTIONAL ▪ Habitual way String fullName = null; System.out.println(fullName.toUpperCase()); if (fullName != null) { System.out.println(fullName.toUpperCase()); }
  • 78. OPTIONAL ▪ Tired of Null Pointer Exceptions? Consider Using Java SE 8's Optional API ▪ Make your code more readable and protect it against null pointer exceptions. ▪ Optional is just a container: it can hold a value of some type T or just be null. ▪ It provides a lot of useful methods so there is no need for explicit null checks.
  • 79. OPTIONAL ▪ New way Optional< String > fullName = Optional.ofNullable( null ); System.out.println( "Full Name is set? " + fullName.isPresent() ); System.out.println( "Full Name: " + fullName.orElseGet( () -> "Nothing" ) ); System.out.println( fullName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) ); Output Full Name is set? false Full Name: Nothing Hey Stranger!
  • 80. OPTIONAL ▪ The isPresent() method returns true if this instance of Optional has non-null value and false otherwise. ▪ The orElseGet() method provides the fallback mechanism in case Optional has null value by accepting the function to generate the default one. ▪ The map() method transforms the current Optional’s value and returns the new Optional instance. ▪ The orElse() method is similar to orElseGet() but instead of function it accepts the default value.
  • 81. OPTIONAL ▪ New way Optional< String > firstName = Optional.of( "Tom" ); System.out.println( "First Name is set? " + firstName.isPresent() ); System.out.println( "First Name: " + firstName.orElseGet( () -> "[none]" ) ); System.out.println( firstName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) ); firstName.ifPresent( fname -> {System.out.println(fname.toUpperCase());}); System.out.println(); There is also another useful method ifPresent which execute actions directly when the value is present, in combination with Lambdas Output First Name is set? true First Name: Tom Hey Tom! TOM
  • 82. Old Way for(String name : names) { int sum = 0; for (int x : numbers) { sum += x; } STREAM - REDUCE List<Integer> numbers = Arrays.asList(4, 5, 3, 9);
  • 83. STREAM - REDUCE List<Integer> numbers = Arrays.asList(4, 5, 3, 9); ▪ An initial value, here 0 ▪ A BinaryOperator<T> to combine two elements and produce a new value ▪ Here you use the lambda (a, b) -> a + b numbers.stream() .reduce(0, (a, b) -> a + b);
  • 84. ▪ Streams can be either sequential or parallel ▪ Operations on sequential streams are performed on a single thread ▪ Operations on parallel streams are performed concurrent STREAM – PARALLEL Parallel Stream int sum = numbers.parallelStream().reduce(0, (a, b) -> a + b);
  • 85. ▪ Creating and using a collector with the Collectors ▪ Reducing streams of data to a single value ▪ Grouping and partitioning data STREAM – COLLECTOR INTRO Collector applies a transforming function to the element and accumulates the result in a data structure that forms the final output
  • 86. Map<String, List<Transaction>> transactionByChannel = new HashMap(); for(Transaction trans : transactions) { List<Transaction> transactionList = transactionByChannel.get(trans.getChannel()); if(transactionList == null) { transactionList = new ArrayList<>(); transactionByChannel.put(trans.getChannel(), transactionList); } transactionList.add(trans); } STREAM – COLLECTOR INTRO Create the map where the grouped Transaction will be accumulated Iterate the list of transaction If there is no entry in the grouping map for this Channel create it Add the currently traversed transaction to the list of transactions with the same channel
  • 87. STREAM – COLLECTOR INTRO Map<String, List<Transaction>> transactionsByChennal = transactions.stream() .collect( Collectors.groupingBy(Transaction::getChannel) );Collectors.groupingBy(Transaction::getChannel)
  • 88. ▪ Summarizing elements ▪ Grouping elements ▪ Partitioning elements STREAM – COLLECTOR INTRO
  • 89. STREAM – SUMMARIZATION List<Integer> numbers = Arrays.asList(2,4,1,8,3,7); IntSummaryStatistics statistics = numbers.stream().collect( Collectors.summarizingInt(num -> num) );Collectors.summarizingInt(num -> num) Summary Sum 25 Min 1 Average 4.16 Max 8 Count 6 IntSummaryStatistics { count=6, sum=25, min=1, average=4.166667, max=8 }
  • 90. STREAM – GROUPING Map<String, List<Transaction>> transactionsByChennal = transactions.stream() .collect( Collectors.groupingBy(Transaction::getChannel) );Collectors.groupingBy(Transaction::getChannel)
  • 91. STREAM – GROUPING final List<String> values = Arrays.asList(“a", “d”, “A”, “b”, “d”); Map<String, Long> count = values.stream() .collect( Collectors.groupingBy(String :: toLowerCase, Collectors.counting)); String :: toLowerCase, Transforming function Aggregate function Collectors.counting {a=2, b=1, d=2}
  • 92. STRINGS AND COMPARATORS ▪ String ▪ new chars method ▪ chars method returns a Stream ▪ Hence map, filter, reduce Stream methods are leveraged to process final String str = “w00t”; str.chars().mapToObj(x-> Character.valueOf((char)x)).forEach(System.out::println); // Only Digits are filtered to print. str.chars().filter(Character::isDigit).mapToObj(x-> Character.valueOf((char)x)).forEach(System.out::println);
  • 93. STRINGS AND COMPARATORS ▪ Method references ▪ String::toUppercase and Character::isDigit ▪ Both Instance and static methods can be referenced ▪ Caveat -> Double::toString ▪ Double has one instance toString() and one static toString()
  • 94. COMPARATOR INTERFACE ▪ Became functional interface J8. ▪ Hence Lambda compatible.
  • 95. COMPARATOR SAMPLE public class Person { private final String name; private final int age; public Person(final String theName, final int theAge) { name = theName; age = theAge; } public String getName() { return name; } public int getAge() { return age; } public int ageDifference(final Person other) { return age - other.age; }}
  • 96. COMPARATOR.REVERSED() ▪ Has a new method reversed(); ▪ Which can be used to reverse the comparator function. Comparator<Person> ascendingComparator = (x,y) -> x.ageDifference(y); Comparator<Person> decendingComparator = ascendingComparator.reversed();
  • 97. MULTIPLE AND FLUENT COMPARISONS ▪ Comparator.comparing ▪ Comparator.thenComparing final Function<Person,Integer> byAge = x -> x.getAge(); final Function<Person,String> byName = x -> x.getName(); ascendingPersons = persons.stream().sorted(comparing(byAge).thenComparing(byName)).collect(toList()); ascendingPersons.forEach(System.out::println);
  • 98. COLLECT METHOD AND COLLECTOR CLASS ▪ The collect method takes a stream of elements and collects or gathers them into a result container. To do that, the method needs to know three things: ▪ How to make a result container (for example, using the ArrayList::new method) ▪ How to add a single element to a result container (for example, using the ArrayList::add method) ▪ How to merge one result container into another (for example, using the ArrayList::addAll method)
  • 99. COLLECTOR CONVENIENT METHODS ▪ toList(); ▪ toSet(); ▪ toMap();
  • 100. ▪ In Java we often execute code eagerly ▪ There are situations we create heavy weight objects only at the moment needed. The delayed object creation is mainly meant for performance reasons LAZY INITIALIZATION Habitual Way public class Heavy { public Heavy() { System.out.println("Heavy created"); } public String toString() { return "Quite heavy"; } } // Lets use an instance of this class in another Holder class named HolderNaive public class HolderNaive { private Heavy heavy; public HolderNaive() { System.out.println("Holder Naive created"); } public Heavy getHeavy() { if(heavy == null) { heavy = new Heavy(); } return heavy; } }
  • 101. Habitual Way final HolderNaive holder = new HolderNaive(); System.out.println("Deferring heavy creation"); System.out.println(holder.getHeavy()); System.out.println(holder.getHeavy()); output: Holder created Deferring heavy creation Heavy created Quite heavy Quite heavy LAZY INITIALIZATION ▪ The above solution is simple but it fails to provide thread safety.
  • 102. LAZY INITIALIZATION Habitual Way // Providing thread safety public synchronized Heavy getHeavy() { if(heavy == null) { heavy = new Heavy(); } return heavy; } ▪ The above solution is quite heavy because every call to the method is synchronized. ▪ We need thread safety until the reference is first created and then onwards unhindered access is needed
  • 103. LAZY INITIALIZATION New Way public class HolderNaive { private Supplier<Heavy> heavy = () -> new Heavy(); public HolderNaive() { System.out.println("Holder Naive created"); } public Heavy getHeavy() { heavy.get(); } } ▪ We can simplify the delayed object creation using the functional interface Supplier<T> which has an abstract method get() that returns an instance. ▪ In other words Supplier<T> is a factory
  • 105. NASHORN ▪ Until Java SE 7, JDKs shipped with a JavaScript scripting engine based on Mozilla Rhino ▪ SE 8 will instead ship with a new engine called Oracle Nashorn ▪ Based on JSR-292 and invokedynamic. ▪ ECMA-compliant JavaScript, currently supports ECMAScript 5.1 ▪ Objects available for Web browsers are not available. For example, console, window
  • 106. TO USE 1. jjs command-line tool[REPL] 2. Oracle Nashorn as an embedded scripting engine inside Java 3. Using Java inside JS
  • 107. JJS REPL var hello = function() { print("Hello Nashorn!"); }; hello();
  • 108. INVOKING JAVASCRIPT FUNCTIONS FROM JAVA ▪ Direct Reference ScriptEngineManager engineManager = new ScriptEngineManager(); ScriptEngine engine = engineManager.getEngineByName("nashorn"); engine.eval("function hello(name) { print("Hello " + name + "!");};"); System.out.println(engine.eval("hello("Banca Sella");")); ▪ File Reference ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("nashorn"); scriptEngine.eval(new FileReader("C:/Users/gbs02362/workspace/J8/src/it/sella/dsn/training/j8/nashorn/he llo.js")); Invocable invocable = (Invocable) scriptEngine; invocable.invokeFunction("hello", "Banca Sella"); invocable.invokeFunction("helloObject", LocalDateTime.now());
  • 109. INVOKING JAVA METHODS FROM JAVASCRIPT ▪ Java.type var ArrayList = Java.type('java.util.ArrayList'); var list = new ArrayList(); list.add('a'); list.add('b'); list.add('c'); for each (var el in list) print(el);
  • 110. INVOKING JAVA METHODS FROM JAVASCRIPT ▪ Without Java.type var map = new java.util.HashMap(); map.put('foo', 'val1'); map.put('bar', 'val2'); for each (var e in map.keySet()) print(e); // foo, bar for each (var e in map.values()) print(e); // val1, val2
  • 111. INVOKING JAVA METHODS FROM JAVASCRIPT ▪ Lambda leveraged var employeeList = new java.util.ArrayList(); employeeList.add("John"); employeeList.add("Joy"); employeeList.add("Krish"); employeeList.add("Kannan"); employeeList.add("Joe"); employeeList.add("Arul"); employeeList.add("Ravi"); employeeList.add("Shiva");
  • 112. LAMBDA LEVERAGED….. employeeList.stream() .filter(function(el) { return el.startsWith("J"); }) .sorted() .forEach(function(el) { print(el); });