SlideShare a Scribd company logo
A brief tour of modern Java
by Sina Madani
A brief history…
• February 1997 – Java 1.1
AWT, inner classes, JDBC, reflection (introspection only), RMI, JavaBeans…
• December 1998 – Java 2
• JIT compiler, Collections framework, JIT compiler, CORBA IDL…
• May 2000 – Java 3
• Hotspot, JNDI, JDPA…
• February 2002 – Java 4
• assert keyword, NIO, exception chaining, IPv6, prefs, APIs for security,
logging, image…
A brief history…
• September 2004 – Java 5 (Java as we know it!)
• Generics, annotations, enum, varargs, for-each, static imports, Scanner,
auto-boxing/unboxing, concurrent utilities (task scheduling, atomics, locks…)
• December 2006 – Java 6 (one of the most popular versions)
• General back-end improvements, nothing new that’s noteworthy
• July 2011 – Java 7 (Project Coin)
• invokedynamic, Strings in switch, type inference (“diamonds”), binary
literals, try-with-resources, fork/join framework, multi-catch, new file I/O…
• March 2014 – Java 8
• July 2017 (we hope!) – Java 9
Why is Java 8 so significant?
• Like Java 5, Java 8 makes fundamental additions to the language
• It (should!) change how programmers think and code
• It embraces functional programming
• It brings Java to the modern era
• Java is “plagued” by its origins
• Lots of “modern” JVM languages are far superior: Groovy, Scala, Kotlin…
• Java 8 makes significant strides to keep up to date
default and static methods in interfaces
• Interface methods can contain a default implementation
• Implementing classes do not need to override default methods
• “Poor man’s multiple inheritance”?
• Partially removes the need for X as interface and AbstractX
• A convenient way to make it less laborious to implement interfaces
• Allows interfaces to evolve without breaking compatibility
• Static methods also allow for evolution – no longer need to have a
wrapper class for implementing utility methods
• Partially motivated by other new features in Java 8
Diamond problem
interface I1 {
default void foo() {
System.out.println(“I1::foo”);
}
}
interface I2 {
default void foo() {
System.out.println(“I2::foo”);
}
}
class BC1 {
public void foo() {
System.out.println(“BC1::foo”);
}
}
class Derived extends BC1 implements I1, I2 {}
• Calling new Derived().foo() results in “BC1::foo”
• What if you have:
class Derived implements I1, I2 {}
new Derived().foo();
• This won’t compile – which foo() do we mean?
• Need to implement it to resolve this issue
• Can still call the base implementations if we want
class Derived implements I1, I2 {
public void foo() {
System.out.println(“Derived::foo”);
I1.super.foo();
I2.super.foo();
}
}
Functional interfaces
• A functional interface has exactly one non-default method
• Runnable is a functional interface – just one method void run()
• An interface with one (unimplemented) method is really a function
• Think about it: when you pass a Runnable to a Thread, you are really telling
the thread to execute the body of the run() method, and nothing else
• Due to Java’s principle of “everything has to be an object”, functions haven’t
been treated with the dignity they deserve.
• Functional interfaces promote functions to “first-class” citizens
• “Hey daddy, can I go alone?” “No, you need to be wrapped in a class.”
• This is no longer the case with Java 8
Lambda expressions
• This is the “headline” feature of Java 8 (deservedly so!)
• A replacement for anonymous functional interface implementations
• You no longer need the “ceremony” for doing this common task
• A lambda expression allows you to define the body of a functional
interface’s method without all the boilerplate around it
Before Java 8
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.print(currentThread().getName());
}
});
With lambdas
Thread t = new Thread (() -> {
System.out.print(currentThread().getName());
});
Method references
• Even more concise than lambdas
• Suppose all you want to do is pass the parameters to another method
• E.g. a Runnable in ThreadFactory
• With lambdas, this is as follows:
ThreadFactory tf = new ThreadFactory(r -> {
return new Thread(r);
});
ThreadFactory before Java 8
ThreadFactory tf = new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
return new Thread(r);
}
};
ThreadFactory with method reference
ThreadFactory tf = Thread::new;
Things to know with lambdas
• Lambdas are not simply syntactic sugar for anonymous inner classes
• No .class files are generated – dynamic dispatch used instead
• Variables of the outer class accessed within the body of lambda
expression should be (effectively) final
• That is, you can’t change the value from within the lambda expression
• Their value must be assigned – need to be statically determinable
• You can’t throw checked exceptions from within a lambda
• Exceptions need to be handled within the lambda
• There are ways to “cheat” this using wrappers
java.util.function
• This is what drives lambda expressions and method references
• Function<T,R> R apply(T t);
• Consumer<T> void accept(T t);
• Supplier<T> T get();
• Predicate<T> boolean test(T t);
• UnaryOperator<T> T apply(T t);
• Also has function types for every combination of int, long, double
• E.g. IntConsumer, IntToLongFunction, DoubleToIntConsumer etc.
• Every interface also has a “Bi” version – accepts two parameters
• e.g. BiFunction<T,U,R> R apply(T t, U u);
Example: Collections.forEach
• Collections API (java.util.Collection and friends) has been updated to
take advantage of the functional interfaces
• One of the most common tasks is to iterate over a collection
Arrays.asList(5, 7, 9, 16).forEach(System.out::println);
• forEach expects a Consumer<T> where T is the type of the collection
Streams API (java.util.stream)
• A Stream is an abstract pipeline of computation
• Allows for performing aggregate operations on data sources
• A data source could be a collection, arrays, iterators, I/O etc.
• java.util.stream only consists of interfaces, not implementation
• Includes Stream<T>, IntStream, DoubleStream, LongStream etc.
• Common operations include:
• map, reduce, filter, findAny, findFirst, forEach, count, distinct, iterate,
generate, limit, min, max, sorted, skip, peek, of, noneMatch, allMatch,
anyMatch, collect, toArray
Properties of Streams
• Lazily evaluated
• Most (“intermediate”) operations just build up the pipeline of computation
• Only “terminal operations” will trigger any actual “work”
• Terminal operations include forEach, collect, findAny, sum, reduce etc.
• Streams do not store any data; nor do they modify the source
• Always return a new Stream for intermediate operations
• Streams are consumable – traverse the data source only once
• Single-pass pipeline and laziness make streams very efficient
• Can be unbounded (infinite streams)
• A convenient way to express data-parallel computations
Language evolution with example
• Suppose you have a set of names
• Create a capitalised subset of the names shorter than 5 characters
E.g. [“Sarah”, “Beth”, “Hamid”, “Marcus”, “Chris”, “Jim”]
becomes
[“BETH”, “CHRIS”, “JIM”]
Java 1
Set getShortNames(Set names) {
Set shortNames = new HashSet();
Iterator iter = names.iterator();
while (iter.hasNext()) {
String name = (String) iter.next();
if (name.length() < 5)
shortNames.add(name.toUpperCase());
}
return shortNames;
}
Java 5
Set<String> getShortNames(Set<String> names) {
Set<String> shortNames = new HashSet<String>();
for (String name : names) {
if (name.length() < 5)
shortNames.add(name.toUpperCase());
}
return shortNames;
}
Java 8
Set<String> getShortNames(Set<String> names) {
return names.stream()
.filter(name -> name.length() < 5)
.map(String::toUpperCase)
.collect(Collectors.toSet());
}
Extension 1
• Get the resulting set of names as a single string separated by commas
• For example:
Set [“Chris”, “Charlie”, “Megan”, “Amy”, “Ben”, “Zoe”]
becomes:
String “CHRIS, AMY, BEN, ZOE”
Imperative style (Java 7)
String getShortNames(Set<String> names) {
StringBuilder shortNames = new StringBuilder();
Iterator iter = names.iterator();
for (int i = 0; i < iter.hasNext(); i++) {
String name = iter.next();
if (name.length() < 5)
shortNames.append(name.toUpperCase());
if (i != names.size())
shortNames.append(“, ”);
}
return shortNames.toString();
}
Declarative style (Java 8)
String getShortNames(Set<String> names) {
return names.stream()
.filter(name -> name.length() < 5)
.map(String::toUpperCase)
.collect(Collectors.joining(“, ”));
}
Extension 2
• The set of names has > 1 million elements
• We need to process them faster
• Create a multi-threaded version to speed things up
Java 1
• “I‘m handing in my resignation.”
Java 5
• “Sorry boss, I’m not feeling well today.”
Java 8
Set<String> getShortNames(Set<String> names) {
return names.parallelStream()
.filter(name -> name.length() < 5)
.map(String::toUpperCase)
.collect(Collectors.toSet());
}
Efficiency example
“Find the square root of the first even number greater than k.”
Suppose:
List<Integer> numbers = asList(1, 2, 5, 3, 7, 8, 12, 10);
and
k = 4
Imperative style
double result = 0d;
for (number : numbers) {
if (number > k && number % 2 == 0) {
result = Math.sqrt(number);
break;
}
}
return result;
Stream (functional style)
return numbers.stream()
.filter(number -> number > k)
.filter(number -> number % 2 == 0)
.map(Math::sqrt)
.findFirst();
Which does more work?
• Imperative style:
• 1 < 4, 2 < 4, 5 > 4, 5 % 2 > 0, 3 < 4, 7 > 4, 7 % 2 > 0, 8 > 4, 8 % 2 == 0, sqrt(8)
• So that’s a total of 10 evaluations to get the answer
• This is what the Stream implementation DOES NOT do:
• Look for all numbers greater than k in the list
• Look for all even numbers (greater than k) in the list
• Get the square root (of all even numbers greater than k) in the list
• The stream composes all intermediate operations
• It applies as many operations to each element first before moving on
• E.g. “is 2 > 4? Move on. Is 5 > 4? Is it even? Move on…”
This is essentially equivalent:
return numbers.stream()
.filter(num -> num > k && num % 2 == 0)
.map(Math::sqrt)
.findFirst();
So a Stream is not only more readable and declarative (what to do, not
how to do it) but it does this as efficiently as the imperative style.
Handling the result
• What if the list contains no even numbers?
• What if the list contains no numbers greater than k?
• What if the list is empty?
• Imperative style:
• return some arbitrary double value
• Could be misinterpreted– no way to know that it couldn’t find a value!
• Nobody likes handling exceptions!
• Functional style:
• return an OptionalDouble
Optional<T>
• An immutable container which may or may not be null
• Calling get() if no value is present will throw an unchecked exception
• Can get an Optional from static methods:
• Optional.of(T value) throws NullPointerException
• Optional.ofNullable(T value)
• Optional.empty()
• Can apply operations based on whether value is present
• ifPresent(Consumer<? super T> consumer)
• map and filter
• T orElse(T other), T orElseGet(Supplier<> other), orElseThrow
Optional chaining example
String customerNameByID(List<Customer> customers, int id) {
return customers.stream()
.filter(c -> c.getID() == id)
.findFirst() //Optional<Customer>
.map(Customer::getName)
.filter(Customer::isValidName)
.orElse(“UNKNOWN”);
}
If customer with id exists, return their name. Otherwise return something else.
Infinite Stream example
long totals = LongStream.generate(() ->
currentTimeMillis() % 1000)
.parallel()
.limit(1_000_000)
.sum();
• This will continuously generate numbers according to the logic
provided in the Supplier and add them up
• If you remove the limit, it’ll max out your CPU forever!
• The stream of numbers isn’t stored – it’s computed on-demand and
fed through the processing pipeline
Parallelism and Asynchronicity
• Parallel streams use the common ForkJoinPool by default
• Uses (number of logical cores - 1) threads
• Can easily get the computation to be handled by another pool
Future<Long> busyWork = new ForkJoinPool(numThreads)
.submit(getComputation(256));
...//do other busy work in the current thread
long execTime = busyWork.get(); //Blocked!
static Callable<Long> getComputation(final int target) {
return () -> {
final long startTime = nanoTime();
IntStream.range(0, target)
.parallel().forEach(loop -> {
int result = ThreadLocalRandom.current()
.ints(0, 2147483647)
.filter(i -> i <= target)
.findAny().getAsInt();
System.out.println(result);
});
return nanoTime()-startTime;
};
}
Triggering computations
• So far, we have seen parallel but synchronous (blocking)
• Even though our computation starts on submission to the Executor, we don’t
know when it’s done
• Calling .get() forces us to wait for the computation to finish
• Can use a ScheduledExecutorService to periodically execute (or
delay execution of) a ScheduledFuture
• But we want to have more flexibility and automation, not delay tasks
• Wouldn’t it be great if we could declare our computations and chain
them together to trigger automatically when they’re done?
• This could be used to handle dependencies between tasks, for example
CompletionStage<T>
• Complex interface (38 methods) for chaining computations
• Computation type may be Function, Consumer or Runnable
• May be triggered by one or two stages (including both and either)
• Execution can be default, async or async with custom Executor
• Flexible exception handling semantics
• BiConsumer/BiFunction where either result or exception is null
• Specify an exception handling function for this stage
• Exceptional completion is propagated downstream (to dependencies)
• toCompletableFuture() returns an interoperable implementation
CompletableFuture<T>
• implements CompletionStage<T>, Future<T> (total 59 methods!)
• Provides a non-blocking API for Future using callbacks
• Cancellation results in exceptional completion
• Can be explicitly completed (or exceptionally completed)
• T getNow(T valueIfAbsent) – non-blocking, returns fallback if absent
• Multiple ways to obtain a CompletableFuture
• supplyAsync, runAsync, completedFuture or no-args constructor
• Can combine any number of CompletableFuture to trigger completion
• static CompletableFuture<Void> allOf(CompletableFuture... cfs)
• static CompletableFuture<Object> anyOf(CompletableFuture... cfs)
CompletableFuture<Void> promise = CompletableFuture
.supplyAsync(() -> compute(target), executor)
.thenApply(Duration::ofNanos)
.thenApply(PerformanceTest::formatDuration)
.thenAccept(System.out::println)
.exceptionally(System.err::println);
for (boolean b = true; !promise.isDone(); b = !b) {
out.println(b ? "tick" : "tock");
Thread.sleep(1000);
}
Nashorn (JavaScript in Java)
• Java-based JavaScript engine (replaces Rhino)
• jjs (terminal command) gives you a JavaScript REPL (like nodejs)
• Can invoke and evaluate JS directly from Java (file or string)
• You can even get the result of the last expression as a native Java object!
• Everything in Nashorn is based on Java objects, so can be passed around
• Can invoke functions/methods written in JS from Java (and vice-versa)!
• Can bind variables into global JS space from Java
• Essentially allows us to write prettier code using JS which can
seamlessly interoperate with existing Java codebase
Other additions/changes
• new Date-Time API (java.time) – completely immutable
• Default methods added to various interfaces (e.g. in Comparator)
• Streams and lambdas used/added to various places in API
• e.g. concurrency utilities, File I/O as well as Collections
• Unsigned arithmetic support
• Parallel array sorting
• Various other back-end improvements (boring stuff)
Java 9 overview
• Modules (“Project Jigsaw”)
• Process API updates
• jshell: command-line REPL for Java
• Stack-walking API – standardized way to get info from stack traces
• HTTP 2.0 client, Money and Currency API, Reactive Streams
• private methods in interfaces?!
• Underscore (“_”) no longer a valid identifier
• Collection factory methods (immutable)
• Native desktop integration (java.awt.desktop)
Possible features in future versions of Java
• Data classes
• Many POJOs are just “dumb data holders”
• Scala-style class declarations would be better – no boilerplate
• Enhanced switch
• Test for types instead of lots of instanceof checks
• Get results from switch – case statements could return values
• Switch on data type patterns
• Project Valhalla – value types with no identity
• Don’t pay for what you don’t use – objects have unnecessary overhead
• “Codes like a class, works like an int” – exploit caching/locality
Questions?
• Thank you for listening!

More Related Content

PDF
Java 7 New Features
Jussi Pohjolainen
 
PPTX
New Features in JDK 8
Martin Toshev
 
PDF
Java SE 8 best practices
Stephen Colebourne
 
PDF
Java 5 and 6 New Features
Jussi Pohjolainen
 
PPT
Scala Talk at FOSDEM 2009
Martin Odersky
 
PPTX
Compilers Are Databases
Martin Odersky
 
PDF
Scala : language of the future
AnsviaLab
 
PDF
The Evolution of Scala / Scala進化論
scalaconfjp
 
Java 7 New Features
Jussi Pohjolainen
 
New Features in JDK 8
Martin Toshev
 
Java SE 8 best practices
Stephen Colebourne
 
Java 5 and 6 New Features
Jussi Pohjolainen
 
Scala Talk at FOSDEM 2009
Martin Odersky
 
Compilers Are Databases
Martin Odersky
 
Scala : language of the future
AnsviaLab
 
The Evolution of Scala / Scala進化論
scalaconfjp
 

What's hot (19)

PPTX
The Evolution of Scala
Martin Odersky
 
PPTX
Java 8 Feature Preview
Jim Bethancourt
 
PPTX
The Road to Lambda - Mike Duigou
jaxconf
 
KEY
Static or Dynamic Typing? Why not both?
Mario Camou Riveroll
 
ODP
Refactoring to Scala DSLs and LiftOff 2009 Recap
Dave Orme
 
PPTX
Scala, Play 2.0 & Cloud Foundry
Pray Desai
 
PDF
Streams in Java 8
Tobias Coetzee
 
PPTX
06 Java Language And OOP Part VI
Hari Christian
 
PDF
Productive Programming in Java 8 - with Lambdas and Streams
Ganesh Samarthyam
 
PDF
Miles Sabin Introduction To Scala For Java Developers
Skills Matter
 
PPTX
Modern sql
Elizabeth Smith
 
PDF
scalaliftoff2009.pdf
Hiroshi Ono
 
PPTX
A Brief Intro to Scala
Tim Underwood
 
PDF
camel-scala.pdf
Hiroshi Ono
 
PDF
An Introduction to Scala for Java Developers
Miles Sabin
 
PDF
Introduction to Functional Programming with Scala
pramode_ce
 
PDF
Quick introduction to scala
Mohammad Hossein Rimaz
 
PDF
New Features Of JDK 7
Deniz Oguz
 
PDF
Solid and Sustainable Development in Scala
scalaconfjp
 
The Evolution of Scala
Martin Odersky
 
Java 8 Feature Preview
Jim Bethancourt
 
The Road to Lambda - Mike Duigou
jaxconf
 
Static or Dynamic Typing? Why not both?
Mario Camou Riveroll
 
Refactoring to Scala DSLs and LiftOff 2009 Recap
Dave Orme
 
Scala, Play 2.0 & Cloud Foundry
Pray Desai
 
Streams in Java 8
Tobias Coetzee
 
06 Java Language And OOP Part VI
Hari Christian
 
Productive Programming in Java 8 - with Lambdas and Streams
Ganesh Samarthyam
 
Miles Sabin Introduction To Scala For Java Developers
Skills Matter
 
Modern sql
Elizabeth Smith
 
scalaliftoff2009.pdf
Hiroshi Ono
 
A Brief Intro to Scala
Tim Underwood
 
camel-scala.pdf
Hiroshi Ono
 
An Introduction to Scala for Java Developers
Miles Sabin
 
Introduction to Functional Programming with Scala
pramode_ce
 
Quick introduction to scala
Mohammad Hossein Rimaz
 
New Features Of JDK 7
Deniz Oguz
 
Solid and Sustainable Development in Scala
scalaconfjp
 
Ad

Viewers also liked (20)

PPTX
Re-implementing Thrift using MDE
Sina Madani
 
PPTX
The Big Fix
Arlen Meyers, MD, MBA
 
PDF
Le détail des play-offs
sportwort
 
PDF
La montagna 11 marzo 2017 qui ed ora
MSFitalia
 
PPTX
Presentación1
andres felipe
 
PPTX
Acts 5, 1 16
odcsoundroom
 
PPTX
Soirée d’information Projet d’implantation d’un sens unique et d’une piste mu...
Ville de Châteauguay
 
PDF
Syllabus Contabilidad Internacional
ERSENUBIA SANTAMARIA VARGAS
 
PDF
Curtain Coating - when the Curtain Falls
TSE TROLLER AG
 
PDF
Ser Cofrade y estar en las Mondas, talavera 2011
Sergio de la Llave Muñoz
 
PPTX
Cv_Delfina_CABA
Delfina Eckart
 
DOC
Evaluacion inicial-5-anos
javierajam
 
PPTX
Sur le chemin du leadership
Ose Coliko
 
PDF
Mapa mercado-de-trabalho
Keila Rodrigues
 
PDF
Capítulo 4 -_apuração_de_resultado_e_escrituração[1]
Tatiana Tenório
 
PPTX
Collaboration tools
Daira Molina
 
PPTX
teniente González
ilisbeth gonzalez
 
PDF
Chartis risk tech 100 vendor highlights IHS Markit
Danielle Goldberg
 
PPTX
BUILDINGS TO REMEMBER
Sanjoy Mudi
 
PDF
HubSpot + Taboola: Winning with Content from Creation to Distribution
Taboola
 
Re-implementing Thrift using MDE
Sina Madani
 
Le détail des play-offs
sportwort
 
La montagna 11 marzo 2017 qui ed ora
MSFitalia
 
Presentación1
andres felipe
 
Acts 5, 1 16
odcsoundroom
 
Soirée d’information Projet d’implantation d’un sens unique et d’une piste mu...
Ville de Châteauguay
 
Syllabus Contabilidad Internacional
ERSENUBIA SANTAMARIA VARGAS
 
Curtain Coating - when the Curtain Falls
TSE TROLLER AG
 
Ser Cofrade y estar en las Mondas, talavera 2011
Sergio de la Llave Muñoz
 
Cv_Delfina_CABA
Delfina Eckart
 
Evaluacion inicial-5-anos
javierajam
 
Sur le chemin du leadership
Ose Coliko
 
Mapa mercado-de-trabalho
Keila Rodrigues
 
Capítulo 4 -_apuração_de_resultado_e_escrituração[1]
Tatiana Tenório
 
Collaboration tools
Daira Molina
 
teniente González
ilisbeth gonzalez
 
Chartis risk tech 100 vendor highlights IHS Markit
Danielle Goldberg
 
BUILDINGS TO REMEMBER
Sanjoy Mudi
 
HubSpot + Taboola: Winning with Content from Creation to Distribution
Taboola
 
Ad

Similar to A brief tour of modern Java (20)

PPT
Java user group 2015 02-09-java8
marctritschler
 
PPT
Java user group 2015 02-09-java8
Marc Tritschler
 
PPTX
What's new in Java 8
Kyle Smith
 
PPTX
Java 7 Whats New(), Whats Next() from Oredev
Mattias Karlsson
 
PDF
Lambdas in Java 8
Tobias Coetzee
 
PDF
Java8
Felipe Mamud
 
PDF
An Introduction to Scala - Blending OO and Functional Paradigms
Miles Sabin
 
PDF
Charles Sharp: Java 8 Streams
jessitron
 
PDF
Spring Day | Spring and Scala | Eberhard Wolff
JAX London
 
KEY
The Why and How of Scala at Twitter
Alex Payne
 
PPTX
Java 8
Sudipta K Paik
 
PDF
Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...
Raffi Khatchadourian
 
PPTX
Lambdas and Laughs
Jim Bethancourt
 
PPTX
Lecture from javaday.bg by Nayden Gochev/ Ivan Ivanov and Mitia Alexandrov
Nayden Gochev
 
PDF
2014 java functional
Demian Neidetcher
 
PPTX
New features in jdk8 iti
Ahmed mar3y
 
PPTX
Java- Updates in java8-Mazenet solution
Mazenetsolution
 
KEY
Scala Introduction
Adrian Spender
 
PPTX
Lambda Expressions Java 8 Features usage
AsmaShaikh478737
 
PPTX
Java SE 8 - New Features
Naveen Hegde
 
Java user group 2015 02-09-java8
marctritschler
 
Java user group 2015 02-09-java8
Marc Tritschler
 
What's new in Java 8
Kyle Smith
 
Java 7 Whats New(), Whats Next() from Oredev
Mattias Karlsson
 
Lambdas in Java 8
Tobias Coetzee
 
An Introduction to Scala - Blending OO and Functional Paradigms
Miles Sabin
 
Charles Sharp: Java 8 Streams
jessitron
 
Spring Day | Spring and Scala | Eberhard Wolff
JAX London
 
The Why and How of Scala at Twitter
Alex Payne
 
Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...
Raffi Khatchadourian
 
Lambdas and Laughs
Jim Bethancourt
 
Lecture from javaday.bg by Nayden Gochev/ Ivan Ivanov and Mitia Alexandrov
Nayden Gochev
 
2014 java functional
Demian Neidetcher
 
New features in jdk8 iti
Ahmed mar3y
 
Java- Updates in java8-Mazenet solution
Mazenetsolution
 
Scala Introduction
Adrian Spender
 
Lambda Expressions Java 8 Features usage
AsmaShaikh478737
 
Java SE 8 - New Features
Naveen Hegde
 

Recently uploaded (20)

PPTX
PFAS Reporting Requirements 2026 Are You Submission Ready Certivo.pptx
Certivo Inc
 
PPTX
Contractor Management Platform and Software Solution for Compliance
SHEQ Network Limited
 
PDF
What to consider before purchasing Microsoft 365 Business Premium_PDF.pdf
Q-Advise
 
PPTX
The-Dawn-of-AI-Reshaping-Our-World.pptxx
parthbhanushali307
 
PPTX
Maximizing Revenue with Marketo Measure: A Deep Dive into Multi-Touch Attribu...
bbedford2
 
PDF
Applitools Platform Pulse: What's New and What's Coming - July 2025
Applitools
 
PDF
ShowUs: Pharo Stream Deck (ESUG 2025, Gdansk)
ESUG
 
PDF
New Download MiniTool Partition Wizard Crack Latest Version 2025
imang66g
 
PPTX
Odoo Integration Services by Candidroot Solutions
CandidRoot Solutions Private Limited
 
PPTX
AI-Ready Handoff: Auto-Summaries & Draft Emails from MQL to Slack in One Flow
bbedford2
 
PDF
Appium Automation Testing Tutorial PDF: Learn Mobile Testing in 7 Days
jamescantor38
 
PDF
Balancing Resource Capacity and Workloads with OnePlan – Avoid Overloading Te...
OnePlan Solutions
 
PPT
Why Reliable Server Maintenance Service in New York is Crucial for Your Business
Sam Vohra
 
PPTX
Role Of Python In Programing Language.pptx
jaykoshti048
 
DOCX
Can You Build Dashboards Using Open Source Visualization Tool.docx
Varsha Nayak
 
PPTX
GALILEO CRS SYSTEM | GALILEO TRAVEL SOFTWARE
philipnathen82
 
PPTX
classification of computer and basic part of digital computer
ravisinghrajpurohit3
 
PDF
Exploring AI Agents in Process Industries
amoreira6
 
PDF
WatchTraderHub - Watch Dealer software with inventory management and multi-ch...
WatchDealer Pavel
 
PPTX
Visualising Data with Scatterplots in IBM SPSS Statistics.pptx
Version 1 Analytics
 
PFAS Reporting Requirements 2026 Are You Submission Ready Certivo.pptx
Certivo Inc
 
Contractor Management Platform and Software Solution for Compliance
SHEQ Network Limited
 
What to consider before purchasing Microsoft 365 Business Premium_PDF.pdf
Q-Advise
 
The-Dawn-of-AI-Reshaping-Our-World.pptxx
parthbhanushali307
 
Maximizing Revenue with Marketo Measure: A Deep Dive into Multi-Touch Attribu...
bbedford2
 
Applitools Platform Pulse: What's New and What's Coming - July 2025
Applitools
 
ShowUs: Pharo Stream Deck (ESUG 2025, Gdansk)
ESUG
 
New Download MiniTool Partition Wizard Crack Latest Version 2025
imang66g
 
Odoo Integration Services by Candidroot Solutions
CandidRoot Solutions Private Limited
 
AI-Ready Handoff: Auto-Summaries & Draft Emails from MQL to Slack in One Flow
bbedford2
 
Appium Automation Testing Tutorial PDF: Learn Mobile Testing in 7 Days
jamescantor38
 
Balancing Resource Capacity and Workloads with OnePlan – Avoid Overloading Te...
OnePlan Solutions
 
Why Reliable Server Maintenance Service in New York is Crucial for Your Business
Sam Vohra
 
Role Of Python In Programing Language.pptx
jaykoshti048
 
Can You Build Dashboards Using Open Source Visualization Tool.docx
Varsha Nayak
 
GALILEO CRS SYSTEM | GALILEO TRAVEL SOFTWARE
philipnathen82
 
classification of computer and basic part of digital computer
ravisinghrajpurohit3
 
Exploring AI Agents in Process Industries
amoreira6
 
WatchTraderHub - Watch Dealer software with inventory management and multi-ch...
WatchDealer Pavel
 
Visualising Data with Scatterplots in IBM SPSS Statistics.pptx
Version 1 Analytics
 

A brief tour of modern Java

  • 1. A brief tour of modern Java by Sina Madani
  • 2. A brief history… • February 1997 – Java 1.1 AWT, inner classes, JDBC, reflection (introspection only), RMI, JavaBeans… • December 1998 – Java 2 • JIT compiler, Collections framework, JIT compiler, CORBA IDL… • May 2000 – Java 3 • Hotspot, JNDI, JDPA… • February 2002 – Java 4 • assert keyword, NIO, exception chaining, IPv6, prefs, APIs for security, logging, image…
  • 3. A brief history… • September 2004 – Java 5 (Java as we know it!) • Generics, annotations, enum, varargs, for-each, static imports, Scanner, auto-boxing/unboxing, concurrent utilities (task scheduling, atomics, locks…) • December 2006 – Java 6 (one of the most popular versions) • General back-end improvements, nothing new that’s noteworthy • July 2011 – Java 7 (Project Coin) • invokedynamic, Strings in switch, type inference (“diamonds”), binary literals, try-with-resources, fork/join framework, multi-catch, new file I/O… • March 2014 – Java 8 • July 2017 (we hope!) – Java 9
  • 4. Why is Java 8 so significant? • Like Java 5, Java 8 makes fundamental additions to the language • It (should!) change how programmers think and code • It embraces functional programming • It brings Java to the modern era • Java is “plagued” by its origins • Lots of “modern” JVM languages are far superior: Groovy, Scala, Kotlin… • Java 8 makes significant strides to keep up to date
  • 5. default and static methods in interfaces • Interface methods can contain a default implementation • Implementing classes do not need to override default methods • “Poor man’s multiple inheritance”? • Partially removes the need for X as interface and AbstractX • A convenient way to make it less laborious to implement interfaces • Allows interfaces to evolve without breaking compatibility • Static methods also allow for evolution – no longer need to have a wrapper class for implementing utility methods • Partially motivated by other new features in Java 8
  • 6. Diamond problem interface I1 { default void foo() { System.out.println(“I1::foo”); } } interface I2 { default void foo() { System.out.println(“I2::foo”); } }
  • 7. class BC1 { public void foo() { System.out.println(“BC1::foo”); } } class Derived extends BC1 implements I1, I2 {} • Calling new Derived().foo() results in “BC1::foo”
  • 8. • What if you have: class Derived implements I1, I2 {} new Derived().foo(); • This won’t compile – which foo() do we mean? • Need to implement it to resolve this issue • Can still call the base implementations if we want class Derived implements I1, I2 { public void foo() { System.out.println(“Derived::foo”); I1.super.foo(); I2.super.foo(); } }
  • 9. Functional interfaces • A functional interface has exactly one non-default method • Runnable is a functional interface – just one method void run() • An interface with one (unimplemented) method is really a function • Think about it: when you pass a Runnable to a Thread, you are really telling the thread to execute the body of the run() method, and nothing else • Due to Java’s principle of “everything has to be an object”, functions haven’t been treated with the dignity they deserve. • Functional interfaces promote functions to “first-class” citizens • “Hey daddy, can I go alone?” “No, you need to be wrapped in a class.” • This is no longer the case with Java 8
  • 10. Lambda expressions • This is the “headline” feature of Java 8 (deservedly so!) • A replacement for anonymous functional interface implementations • You no longer need the “ceremony” for doing this common task • A lambda expression allows you to define the body of a functional interface’s method without all the boilerplate around it
  • 11. Before Java 8 Thread t = new Thread(new Runnable() { @Override public void run() { System.out.print(currentThread().getName()); } });
  • 12. With lambdas Thread t = new Thread (() -> { System.out.print(currentThread().getName()); });
  • 13. Method references • Even more concise than lambdas • Suppose all you want to do is pass the parameters to another method • E.g. a Runnable in ThreadFactory • With lambdas, this is as follows: ThreadFactory tf = new ThreadFactory(r -> { return new Thread(r); });
  • 14. ThreadFactory before Java 8 ThreadFactory tf = new ThreadFactory() { @Override public Thread newThread(Runnable r) { return new Thread(r); } };
  • 15. ThreadFactory with method reference ThreadFactory tf = Thread::new;
  • 16. Things to know with lambdas • Lambdas are not simply syntactic sugar for anonymous inner classes • No .class files are generated – dynamic dispatch used instead • Variables of the outer class accessed within the body of lambda expression should be (effectively) final • That is, you can’t change the value from within the lambda expression • Their value must be assigned – need to be statically determinable • You can’t throw checked exceptions from within a lambda • Exceptions need to be handled within the lambda • There are ways to “cheat” this using wrappers
  • 17. java.util.function • This is what drives lambda expressions and method references • Function<T,R> R apply(T t); • Consumer<T> void accept(T t); • Supplier<T> T get(); • Predicate<T> boolean test(T t); • UnaryOperator<T> T apply(T t); • Also has function types for every combination of int, long, double • E.g. IntConsumer, IntToLongFunction, DoubleToIntConsumer etc. • Every interface also has a “Bi” version – accepts two parameters • e.g. BiFunction<T,U,R> R apply(T t, U u);
  • 18. Example: Collections.forEach • Collections API (java.util.Collection and friends) has been updated to take advantage of the functional interfaces • One of the most common tasks is to iterate over a collection Arrays.asList(5, 7, 9, 16).forEach(System.out::println); • forEach expects a Consumer<T> where T is the type of the collection
  • 19. Streams API (java.util.stream) • A Stream is an abstract pipeline of computation • Allows for performing aggregate operations on data sources • A data source could be a collection, arrays, iterators, I/O etc. • java.util.stream only consists of interfaces, not implementation • Includes Stream<T>, IntStream, DoubleStream, LongStream etc. • Common operations include: • map, reduce, filter, findAny, findFirst, forEach, count, distinct, iterate, generate, limit, min, max, sorted, skip, peek, of, noneMatch, allMatch, anyMatch, collect, toArray
  • 20. Properties of Streams • Lazily evaluated • Most (“intermediate”) operations just build up the pipeline of computation • Only “terminal operations” will trigger any actual “work” • Terminal operations include forEach, collect, findAny, sum, reduce etc. • Streams do not store any data; nor do they modify the source • Always return a new Stream for intermediate operations • Streams are consumable – traverse the data source only once • Single-pass pipeline and laziness make streams very efficient • Can be unbounded (infinite streams) • A convenient way to express data-parallel computations
  • 21. Language evolution with example • Suppose you have a set of names • Create a capitalised subset of the names shorter than 5 characters E.g. [“Sarah”, “Beth”, “Hamid”, “Marcus”, “Chris”, “Jim”] becomes [“BETH”, “CHRIS”, “JIM”]
  • 22. Java 1 Set getShortNames(Set names) { Set shortNames = new HashSet(); Iterator iter = names.iterator(); while (iter.hasNext()) { String name = (String) iter.next(); if (name.length() < 5) shortNames.add(name.toUpperCase()); } return shortNames; }
  • 23. Java 5 Set<String> getShortNames(Set<String> names) { Set<String> shortNames = new HashSet<String>(); for (String name : names) { if (name.length() < 5) shortNames.add(name.toUpperCase()); } return shortNames; }
  • 24. Java 8 Set<String> getShortNames(Set<String> names) { return names.stream() .filter(name -> name.length() < 5) .map(String::toUpperCase) .collect(Collectors.toSet()); }
  • 25. Extension 1 • Get the resulting set of names as a single string separated by commas • For example: Set [“Chris”, “Charlie”, “Megan”, “Amy”, “Ben”, “Zoe”] becomes: String “CHRIS, AMY, BEN, ZOE”
  • 26. Imperative style (Java 7) String getShortNames(Set<String> names) { StringBuilder shortNames = new StringBuilder(); Iterator iter = names.iterator(); for (int i = 0; i < iter.hasNext(); i++) { String name = iter.next(); if (name.length() < 5) shortNames.append(name.toUpperCase()); if (i != names.size()) shortNames.append(“, ”); } return shortNames.toString(); }
  • 27. Declarative style (Java 8) String getShortNames(Set<String> names) { return names.stream() .filter(name -> name.length() < 5) .map(String::toUpperCase) .collect(Collectors.joining(“, ”)); }
  • 28. Extension 2 • The set of names has > 1 million elements • We need to process them faster • Create a multi-threaded version to speed things up
  • 29. Java 1 • “I‘m handing in my resignation.”
  • 30. Java 5 • “Sorry boss, I’m not feeling well today.”
  • 31. Java 8 Set<String> getShortNames(Set<String> names) { return names.parallelStream() .filter(name -> name.length() < 5) .map(String::toUpperCase) .collect(Collectors.toSet()); }
  • 32. Efficiency example “Find the square root of the first even number greater than k.” Suppose: List<Integer> numbers = asList(1, 2, 5, 3, 7, 8, 12, 10); and k = 4
  • 33. Imperative style double result = 0d; for (number : numbers) { if (number > k && number % 2 == 0) { result = Math.sqrt(number); break; } } return result;
  • 34. Stream (functional style) return numbers.stream() .filter(number -> number > k) .filter(number -> number % 2 == 0) .map(Math::sqrt) .findFirst();
  • 35. Which does more work? • Imperative style: • 1 < 4, 2 < 4, 5 > 4, 5 % 2 > 0, 3 < 4, 7 > 4, 7 % 2 > 0, 8 > 4, 8 % 2 == 0, sqrt(8) • So that’s a total of 10 evaluations to get the answer • This is what the Stream implementation DOES NOT do: • Look for all numbers greater than k in the list • Look for all even numbers (greater than k) in the list • Get the square root (of all even numbers greater than k) in the list • The stream composes all intermediate operations • It applies as many operations to each element first before moving on • E.g. “is 2 > 4? Move on. Is 5 > 4? Is it even? Move on…”
  • 36. This is essentially equivalent: return numbers.stream() .filter(num -> num > k && num % 2 == 0) .map(Math::sqrt) .findFirst(); So a Stream is not only more readable and declarative (what to do, not how to do it) but it does this as efficiently as the imperative style.
  • 37. Handling the result • What if the list contains no even numbers? • What if the list contains no numbers greater than k? • What if the list is empty? • Imperative style: • return some arbitrary double value • Could be misinterpreted– no way to know that it couldn’t find a value! • Nobody likes handling exceptions! • Functional style: • return an OptionalDouble
  • 38. Optional<T> • An immutable container which may or may not be null • Calling get() if no value is present will throw an unchecked exception • Can get an Optional from static methods: • Optional.of(T value) throws NullPointerException • Optional.ofNullable(T value) • Optional.empty() • Can apply operations based on whether value is present • ifPresent(Consumer<? super T> consumer) • map and filter • T orElse(T other), T orElseGet(Supplier<> other), orElseThrow
  • 39. Optional chaining example String customerNameByID(List<Customer> customers, int id) { return customers.stream() .filter(c -> c.getID() == id) .findFirst() //Optional<Customer> .map(Customer::getName) .filter(Customer::isValidName) .orElse(“UNKNOWN”); } If customer with id exists, return their name. Otherwise return something else.
  • 40. Infinite Stream example long totals = LongStream.generate(() -> currentTimeMillis() % 1000) .parallel() .limit(1_000_000) .sum(); • This will continuously generate numbers according to the logic provided in the Supplier and add them up • If you remove the limit, it’ll max out your CPU forever! • The stream of numbers isn’t stored – it’s computed on-demand and fed through the processing pipeline
  • 41. Parallelism and Asynchronicity • Parallel streams use the common ForkJoinPool by default • Uses (number of logical cores - 1) threads • Can easily get the computation to be handled by another pool Future<Long> busyWork = new ForkJoinPool(numThreads) .submit(getComputation(256)); ...//do other busy work in the current thread long execTime = busyWork.get(); //Blocked!
  • 42. static Callable<Long> getComputation(final int target) { return () -> { final long startTime = nanoTime(); IntStream.range(0, target) .parallel().forEach(loop -> { int result = ThreadLocalRandom.current() .ints(0, 2147483647) .filter(i -> i <= target) .findAny().getAsInt(); System.out.println(result); }); return nanoTime()-startTime; }; }
  • 43. Triggering computations • So far, we have seen parallel but synchronous (blocking) • Even though our computation starts on submission to the Executor, we don’t know when it’s done • Calling .get() forces us to wait for the computation to finish • Can use a ScheduledExecutorService to periodically execute (or delay execution of) a ScheduledFuture • But we want to have more flexibility and automation, not delay tasks • Wouldn’t it be great if we could declare our computations and chain them together to trigger automatically when they’re done? • This could be used to handle dependencies between tasks, for example
  • 44. CompletionStage<T> • Complex interface (38 methods) for chaining computations • Computation type may be Function, Consumer or Runnable • May be triggered by one or two stages (including both and either) • Execution can be default, async or async with custom Executor • Flexible exception handling semantics • BiConsumer/BiFunction where either result or exception is null • Specify an exception handling function for this stage • Exceptional completion is propagated downstream (to dependencies) • toCompletableFuture() returns an interoperable implementation
  • 45. CompletableFuture<T> • implements CompletionStage<T>, Future<T> (total 59 methods!) • Provides a non-blocking API for Future using callbacks • Cancellation results in exceptional completion • Can be explicitly completed (or exceptionally completed) • T getNow(T valueIfAbsent) – non-blocking, returns fallback if absent • Multiple ways to obtain a CompletableFuture • supplyAsync, runAsync, completedFuture or no-args constructor • Can combine any number of CompletableFuture to trigger completion • static CompletableFuture<Void> allOf(CompletableFuture... cfs) • static CompletableFuture<Object> anyOf(CompletableFuture... cfs)
  • 46. CompletableFuture<Void> promise = CompletableFuture .supplyAsync(() -> compute(target), executor) .thenApply(Duration::ofNanos) .thenApply(PerformanceTest::formatDuration) .thenAccept(System.out::println) .exceptionally(System.err::println); for (boolean b = true; !promise.isDone(); b = !b) { out.println(b ? "tick" : "tock"); Thread.sleep(1000); }
  • 47. Nashorn (JavaScript in Java) • Java-based JavaScript engine (replaces Rhino) • jjs (terminal command) gives you a JavaScript REPL (like nodejs) • Can invoke and evaluate JS directly from Java (file or string) • You can even get the result of the last expression as a native Java object! • Everything in Nashorn is based on Java objects, so can be passed around • Can invoke functions/methods written in JS from Java (and vice-versa)! • Can bind variables into global JS space from Java • Essentially allows us to write prettier code using JS which can seamlessly interoperate with existing Java codebase
  • 48. Other additions/changes • new Date-Time API (java.time) – completely immutable • Default methods added to various interfaces (e.g. in Comparator) • Streams and lambdas used/added to various places in API • e.g. concurrency utilities, File I/O as well as Collections • Unsigned arithmetic support • Parallel array sorting • Various other back-end improvements (boring stuff)
  • 49. Java 9 overview • Modules (“Project Jigsaw”) • Process API updates • jshell: command-line REPL for Java • Stack-walking API – standardized way to get info from stack traces • HTTP 2.0 client, Money and Currency API, Reactive Streams • private methods in interfaces?! • Underscore (“_”) no longer a valid identifier • Collection factory methods (immutable) • Native desktop integration (java.awt.desktop)
  • 50. Possible features in future versions of Java • Data classes • Many POJOs are just “dumb data holders” • Scala-style class declarations would be better – no boilerplate • Enhanced switch • Test for types instead of lots of instanceof checks • Get results from switch – case statements could return values • Switch on data type patterns • Project Valhalla – value types with no identity • Don’t pay for what you don’t use – objects have unnecessary overhead • “Codes like a class, works like an int” – exploit caching/locality
  • 51. Questions? • Thank you for listening!

Editor's Notes

  • #2: http://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html http://openjdk.java.net/projects/jdk9/
  • #3: https://en.wikipedia.org/wiki/Java_version_history
  • #5: “Plague” Architects admit they’d have done things differently if they could go back in time Design heavily influenced by what was going on in 1995 Need to “steal” C++ programmers Familiar syntax and constructs Promote OO Worst HelloWorld ever? (too much ceremony) Mutability is the default Checked exceptions Single inheritance “Generics” are tacked on No operator overloading No value types (like structs)
  • #6: https://youtu.be/GphO9fWhlAg
  • #7: https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem
  • #11: https://youtu.be/1OpAgZvYXLQ
  • #17: http://stackoverflow.com/questions/27644361/how-can-i-throw-checked-exceptions-from-inside-java-8-streams
  • #18: https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html
  • #20: https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
  • #21: https://youtu.be/1OpAgZvYXLQ?t=2h5m
  • #36: [1, 2, 5, 3, 7, 8, 12, 10], k=4
  • #37: Short-circuited
  • #39: https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
  • #40: https://youtu.be/Ej0sss6cq14
  • #42: submit takes a Callable<V> and returns a ForkJoinTask<V> ForkJoinTask implements Future
  • #43: Easy way to do “embarrassingly parallel” for-loops
  • #44: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html
  • #45: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html CompletionStage interface has 38 methods determined in a (3x3x3)+(3x3+1) + 1 “toCompleteableFuture()” The first aspect (what triggers a stage): Methods with names starting with “then” are for adding another stage to be triggered when a single stage completes. Methods with names containing “both” are for adding another stage to be triggered when two previous stages both complete. Methods with names containing “either” are for adding another stage to be triggered when either one of two previous stages completes. The second aspect (whether the computation takes an argument and returns a result): Methods with names containing “apply” take a Function, which takes an argument (the result of the previous stage) and return a result (the argument for the next stage). Methods with names containing “accept” take a Consumer, which takes an argument but does not return a result. Methods with names containing “run” take a Runnable, which takes no arguments and does not return a result. The third aspect (how the execution of the computation is arranged): Methods with names which do not end in “async” execute the computation using the stage’s default execution facility. Methods with names that end in “async” execute the computation using the stage’s default asynchronous execution facility. Methods with names that end in “async” and that also take an Executor argument, execute the computation using the specified Executor. Lastly, there four handler methods for dealing with exceptions and/or more general “meta-level” aspects of computations http://www.jesperdj.com/2015/09/26/the-future-is-completable-in-java-8/
  • #46: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html https://youtu.be/-MBPQ7NIL_Y?t=18m https://youtu.be/HdnHmbFg_hw
  • #47: https://blog.krecan.net/2013/12/25/completablefutures-why-to-use-async-methods/ http://fahdshariff.blogspot.co.uk/2016/06/java-8-completablefuture-vs-parallel.html
  • #48: http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/ https://youtu.be/lZgbTAZwerc?t=21m
  • #49: http://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html
  • #50: https://www.sitepoint.com/ultimate-guide-to-java-9/ https://youtu.be/fxB9cVNcyZo http://openjdk.java.net/projects/jdk9/ http://openjdk.java.net/jeps/261 http://openjdk.java.net/jeps/259 http://openjdk.java.net/jeps/213 https://adtmag.com/blogs/watersworks/2015/08/java-9-hack.aspx
  • #51: https://youtu.be/oGll155-vuQ?t=22m – fancy switch https://youtu.be/oGll155-vuQ?t=32m22s – Value types Would be nice to have default parameters instead of having to make factory methods and lots of constructors