Java 8 was released in 2014 and introduced many new features including lambda expressions, default methods on interfaces, streams, date/time API improvements and more. Some key updates were the addition of lambda expressions to support functional programming, default and static methods on interfaces to allow interface evolution, and streams to provide a powerful abstraction for processing collections of elements. The date/time API was also overhauled, drawing inspiration from Joda-Time to provide an immutable and more logically structured date/time library.
3. JAVA 8, what more ?
● JAVA 8 is for JAVA 7 what JAVA 5 was for JAVA 1.4
● Lot’s of cool stuff
● Finally fonctional programming oriented
● With great power comes great responsability
● Ok, let’s dive into
5. Lambdas : let’s blow your mind
Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.println( e ));
Arrays.asList( "a", "b", "d" ).forEach( e -> {
System.out.print( e );
System.out.print( e );
} );
Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );
6. Lambdas : some explanations
● Anonymous method
● To unlearn what you’ve learned, you have to
● (argtype arg...) -> { return some expression.. probably using these arguments }
● Type inference : JVM compiler guess for you args types
● Welcome to functional programming !
8. Functional interfaces : let’s be friends
● Interfaces with only ONE abstract method
● Can contains static and default method (next slide, don’t panic)
● Most of generic functional use case already in java.util.function package
○ Function, Supplier, Consumer, Predicate, etc.
● The backbone of lambda
@FunctionalInterface
public interface Functional {
void method();
}
10. Interface’s Default Methods : abstract death ?
● Not required to be implemented
● Inherited by default
● Overridden allowed
● Public visibility only
11. Interface’s Default Methods : abstract death ?
private interface Defaulable {
// Interfaces now allow default methods, the implementer may or
// may not implement (override) them.
default String notRequired() {
return "Default implementation";
}
}
private static class DefaultableImpl implements Defaulable {
}
private static class OverridableImpl implements Defaulable {
@Override
public String notRequired() {
return "Overridden implementation";
}
}
12. Interface’s Static Methods : tooling in interface
● Act as static class method
● An interface can now contain all the tooling
private interface DefaulableFactory {
// Interfaces now allow static methods
static Defaulable create( Supplier< Defaulable > supplier ) {
return supplier.get();
}
}
14. Method References : let’s take some shortcuts
● Another way, more concise, to refer directly to existing methods
● Constructor reference
● Static method reference
● Instance method reference
● Instance method reference using Class
15. Method reference : example please !
public class Example {
public int add(int a, int b) {
return a + b;
}
public static int mul(int a, int b) {
return a * b;
}
public String lower(String a) {
return a.toLowerCase();
}
public void printDate(Date date) {
System.out.println(date);
}
public void oper(IntBinaryOperator operator, int a, int b) {
System.out.println(operator.applyAsInt(a, b));
}
public void operS(Function<String, String> stringOperator, String a) {
System.out.println(stringOperator.apply(a));
}
public GregorianCalendar operC(Supplier<GregorianCalendar> supplier) {
return supplier.get();
}
}
17. Static method reference
● Lambda way
● Method reference way
ex.oper((a, b) -> Example.mul(a, b), 1, 2);
ex.oper(Example::mul, 1, 2);
18. Instance method reference
● Lambda way
● Method reference way
ex.oper((a, b) -> ex.add(a, b), 1, 2);
ex.oper(ex::add, 1, 2);
19. Instance method reference using class
● Lambda way
● Method reference way
ex.operS(String::toLowerCase, "STRING");
ex.operS(s->s.toLowerCase(), "STRING");
20. Method References : WARNING !!!
Should be assignable to a functionnal interface
22. Repeating annotations : hide me this
● Same annotation can be repeat several times
● How to
@Schedule(dayOfMonth="last")
@Schedule(dayOfWeek="Fri", hour="23")
public void doPeriodicCleanup() { ... }
@Repeatable(Schedules.class)
public @interface Schedule {
String dayOfMonth() default "first";
String dayOfWeek() default "Mon";
int hour() default 12;
}
public @interface Schedules {
Schedule[] value();
}
28. Optional< String > fullName = Optional.ofNullable( null );
System.out.println( "Full Name is set? " + fullName.isPresent() );
System.out.println( "Full Name: " + fullName.orElseGet( () -> "[none]" ) );
System.out.println( fullName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );
Full Name is set? false
Full Name: [none]
Hey Stranger!
Optional is not an option : end of NullPointer ?
29. 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!" ) );
First Name is set? true
First Name: Tom
Hey Tom!
Optional is not an option : end of NullPointer ?
31. ● Create a pipeline made of operations
● Terminal operation could produce another data store
● Parallelization
Streams : THIS IS map/reduce !!!
32. final Collection< Task > tasks = Arrays.asList(
new Task( Status.OPEN, 5 ),
new Task( Status.OPEN, 13 ),
new Task( Status.CLOSED, 8 )
);
// Calculate total points of all active tasks using sum()
final long totalPointsOfOpenTasks = tasks
.stream()
.filter( task -> task.getStatus() == Status.OPEN )
.mapToInt( Task::getPoints )
.sum();
System.out.println( "Total points: " + totalPointsOfOpenTasks );
Total points: 18
Streams : THIS IS map/reduce !!!
33. final Collection< Task > tasks = Arrays.asList(
new Task( Status.OPEN, 5 ),
new Task( Status.OPEN, 13 ),
new Task( Status.CLOSED, 8 )
);
// Group tasks by their status
final Map< Status, List< Task > > map = tasks
.stream()
.collect( Collectors.groupingBy( Task::getStatus ) );
System.out.println( map );
{CLOSED=[[CLOSED, 8]], OPEN=[[OPEN, 5], [OPEN, 13]]}
Streams : THIS IS map/reduce !!!
34. final Collection< Task > tasks = Arrays.asList(
new Task( Status.OPEN, 5 ),
new Task( Status.OPEN, 13 ),
new Task( Status.CLOSED, 8 )
);
// Calculate the weight of each tasks (as percent of total points)
final Collection< String > result = tasks
.stream() // Stream< String >
.mapToInt( Task::getPoints ) // IntStream
.asLongStream() // LongStream
.mapToDouble( points -> points / totalPoints ) // DoubleStream
.boxed() // Stream< Double >
.mapToLong( weigth -> ( long )( weigth * 100 ) ) // LongStream
.mapToObj( percentage -> percentage + "%" ) // Stream< String>
.collect( Collectors.toList() ); // List< String >
System.out.println( result );
[19%, 50%, 30%]
Streams : THIS IS map/reduce !!!
36. ● Inspired by JODA Time : made by developpers for developpers
● One package : java.time
● IMMUTABLE by design
Date/Time API : Joda time was here...
37. Date/Time API : Clock
// Get the system clock as UTC offset
final Clock clock = Clock.systemUTC();
System.out.println( clock.instant() );
System.out.println( clock.millis() );
2014-04-12T15:19:29.282Z
1397315969360
38. Date/Time API : LocalDate / LocalTime
// Get the local date and local time
final LocalDate date = LocalDate.now();
final LocalDate dateFromClock = LocalDate.now( clock );
System.out.println( date );
System.out.println( dateFromClock );
// Get the local date and local time
final LocalTime time = LocalTime.now();
final LocalTime timeFromClock = LocalTime.now( clock );
System.out.println( time );
System.out.println( timeFromClock );
2014-04-12
2014-04-12
11:25:54.568
15:25:54.568
39. Date/Time API : ZoneDateTime
// Get the zoned date/time
final Clock clock = Clock.systemUTC();
final ZonedDateTime zonedDatetime = ZonedDateTime.now();
final ZonedDateTime zonedDatetimeFromClock =
ZonedDateTime.now( clock );
final ZonedDateTime zonedDatetimeFromZone =
ZonedDateTime.now( ZoneId.of( "America/Los_Angeles" ) );
System.out.println( zonedDatetime );
System.out.println( zonedDatetimeFromClock );
System.out.println( zonedDatetimeFromZone );
2014-04-12T11:47:01.017-04:00
[America/New_York]
2014-04-12T15:47:01.017Z
2014-04-12T08:47:01.017-07:00
[America/Los_Angeles]
40. Date/Time API : Duration
// Get duration between two dates
final LocalDateTime from =
LocalDateTime.of( 2014, Month.APRIL, 16, 0, 0, 0 );
final LocalDateTime to =
LocalDateTime.of( 2015, Month.APRIL, 16, 23, 59, 59 );
final Duration duration = Duration.between( from, to );
System.out.println( "Duration in days: " + duration.toDays() );
System.out.println( "Duration in hours: " + duration.toHours() );
Duration in days: 365
Duration in hours: 8783
42. And so many other things
● Nashorn JavaScript Engine : evaluate JavaScript in JAVA
● Base64 standard support
○ URL-friendly encoder/decoder
○ MIME-friendly encoder/decoder
● Parallel Arrays
● Class dependency analyzer : jdeps
● XX:PermSize / XX:MaxPermSize respectivly replaced by XX:MetaSpaceSize
/ XX:MaxMetaSpaceSize
● String.join() / Objects.nonNull()
● Reflection api support TypeName, GenericString, access Generic type, etc.
● ...