java 8
TRANSCRIPT
A bit of history
● (“1.0”) -> LocalDate.of(1996, Month.JANUARY, 23)● (“1.1”) -> LocalDate.of(1997, Month.FEBRUARY, 19)● (“1.2”) -> LocalDate.of(1998, Month.DECEMBER, 9)● (“1.3”) -> LocalDate.of(2000, Month.MAY, 8)● (“1.4”) -> LocalDate.of(2002, Month.FEBRUARY, 6)● (“1.5”) -> LocalDate.of(2004, Month.SEPTEMBER, 30)● (“1.6”) -> LocalDate.of(2006, Month.DECEMBER, 11)● (“1.7”) -> LocalDate.of(2011, Month.JULY, 7)● (“1.8”) -> LocalDate.of(2014, Month.MARCH, 15)
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
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 ) );
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 !
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();
}
Interface’s Default Methods : abstract death ?
● Not required to be implemented
● Inherited by default
● Overridden allowed
● Public visibility only
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"; }}
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(); }}
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
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(); } }
Constructor reference
ex.operC(()->{ return new GregorianCalendar();})
ex.operC(GregorianCalendar::new);
● Lambda way
● Method reference way
Static method reference
● Lambda way
● Method reference way
ex.oper((a, b) -> Example.mul(a, b), 1, 2);
ex.oper(Example::mul, 1, 2);
Instance method reference
● Lambda way
● Method reference way
ex.oper((a, b) -> ex.add(a, b), 1, 2);
ex.oper(ex::add, 1, 2);
Instance method reference using class
● Lambda way
● Method reference way
ex.operS(String::toLowerCase, "STRING");
ex.operS(s->s.toLowerCase(), "STRING");
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();}
Extended Annotations Support : annotation everywhere !
● ElementType.TYPE_USE -> Annotation on type use● ElementType.TYPE_PARAMETER -> Annotation on type variable
@NonNull String name; // Type useList<@NonNull String> names; // Type parameterclass UnmodifiableList<T> implements @Readonly List<@Readonly T> {...}email = (@Email String) input;new @Information MyObject();void doSomething() throws @ImportantForMe MyException { ... }
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? falseFull Name: [none]Hey Stranger!
Optional is not an option : end of NullPointer ?
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? trueFirst Name: TomHey Tom!
Optional is not an option : end of NullPointer ?
● Create a pipeline made of operations
● Terminal operation could produce another data store
● Parallelization
Streams : THIS IS map/reduce !!!
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 !!!
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 statusfinal 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 !!!
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 !!!
● Inspired by JODA Time : made by developpers for developpers
● One package : java.time
● IMMUTABLE by design
Date/Time API : Joda time was here...
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.282Z1397315969360
Date/Time API : LocalDate / LocalTime
// Get the local date and local timefinal LocalDate date = LocalDate.now();final LocalDate dateFromClock = LocalDate.now( clock ); System.out.println( date );System.out.println( dateFromClock ); // Get the local date and local timefinal LocalTime time = LocalTime.now();final LocalTime timeFromClock = LocalTime.now( clock ); System.out.println( time );System.out.println( timeFromClock );
2014-04-122014-04-1211:25:54.56815:25:54.568
Date/Time API : ZoneDateTime
// Get the zoned date/timefinal 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]
Date/Time API : Duration
// Get duration between two datesfinal 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: 365Duration in hours: 8783
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.● ...