Below
are the most recent features which is introduced in Java 8:
- Lambda
Expressions: It
is a Java function that you can share or refer to as an object.
- Method
interference: It
uses function as a criterion to implement a method.
- Functional
Interference: Every
functional interference is associated with a single abstract method which
is known as the functional method.
- Default
Method: It
is useful in implementing methods in the interfaces that help enable the
‘interface evolution’ potential.
- Date
Time API: It
is an improved yet inspired version of java time APIs to deal with the
drawbacks of the last version.
- Stream
API is
referred to as the abstract layer, which helps to pipeline the processing
data.
- Optional: The wrapper class is useful in
checking the null values and processing the further data.
- JavaScript and Nashorn Engine: It is the improved version of the JavaScript Engine, which is useful in enabling its functionality in Java, replacing Rhino.
In
which programming paradigm Java 8 falls?
- Object-oriented
programming language.
- Functional
programming language.
- Procedural
programming language.
- Logic programming language
What
are the significant advantages of Java 8?
- Compact,
readable, and reusable code.
- Less
boilerplate code.
- Parallel
operations and execution.
- Can
be ported across operating systems.
- High
stability.
- Stable
environment.
- Adequate
support
What is MetaSpace? How does it differ from PermGen?
PremGen: MetaData information of
classes was stored in PremGen (Permanent-Generation) memory type before Java 8.
PremGen is fixed in size and cannot be dynamically resized. It was a contiguous
Java Heap Memory.
MetaSpace: Java 8 stores the MetaData of
classes in native memory called 'MetaSpace'. It is not a contiguous Heap Memory
and hence can be grown dynamically which helps to overcome the size
constraints. This improves the garbage collection, auto-tuning, and de-allocation
of metadata.
What is the use of the @FunctionalInterface annotation?
This
annotation is used in functional interfaces to add more readability to the code
as an informative aspect. However, it does not affect the runtime or the
semantics of the code.
What
is the meaning of functional interfaces in Java 8?
Functional
interfaces in Java 8 are interfaces having a single abstract method.
Following
are the three types of methods that can be present:
- The
static method
- The
default method
- The
overridden class method
What is
the meaning of method reference in Java 8?
Method
references are used in Java 8 to refer to methods of functional interfaces. It
can be considered as a short-code version of using a lambda expression.
The
following is the expression for a method reference:
Class::methodname
For
e.g.:
Integer::parseInt(str)
\\ method reference
str
-> Integer.ParseInt(str); \\ equivalent lambda
What is the lambda expression in Java and How does a lambda expression relate to a functional interface?
Lambda
expression is a type of function without a name. It may or may not have results
and parameters. It is known as an anonymous function as it does not have type
information by itself. It is executed on-demand. It is beneficial in iterating,
filtering, and extracting data from a collection.
As lambda
expressions are similar to anonymous functions, they can only be applied to the
single abstract method of Functional Interface. It will infer the return type,
type, and several arguments from the signature of the abstract method of
functional interface.
Describe
the syntax of a lambda expression.
Lambda
expressions can be divided into three parts as shown in the below syntax:
//Lambda
expression: (int a, int b) -> { System.out.println(a+b); return a+b;}
- Arguments: A lambda expression can have
zero or more arguments at any point in time.
- Array
token: It is
used to point to the body of the expression.
- Body: The body consists of
expressions and statements. Braces are not required if it has onl a single
statement.
What are the types and common ways to use lambda expressions?
A lambda
expression does not have any specific type by itself. A lambda expression
receives type once it is assigned to a functional interface. That same lambda
expression can be assigned to different functional interface types and can have
a different type.
For eg
consider expression s -> s.isEmpty() :
Predicate<String>
stringPredicate = s -> s.isEmpty();
Predicate<List> listPredicate = s -> s.isEmpty();
Function<String, Boolean> func = s -> s.isEmpty();
Consumer<String> stringConsumer = s -> s.isEmpty();
Common
ways to use the expression
Assignment
to a functional Interface —> Predicate<String> stringPredicate =
s -> s.isEmpty();
Can be passed as a parameter that has a functional type —> stream.filter(s
-> s.isEmpty())
Returning it from a function —> return s -> s.isEmpty()
Casting it to a functional type —> (Predicate<String>) s ->
s.isEmpty()
Can a
functional interface extend/inherit another interface?
A
functional interface cannot extend another interface with abstract methods as
it will void the rule of one abstract method per functional interface. E.g:
interface Parent {
public int parentMethod();
}
@FunctionalInterface
// This cannot be FunctionalInterface
interface Child extends Parent
{
public int childMethod();
//
It will also extend the abstract method of the Parent Interface
//
Hence it will have more than one abstract method
//
And will give a compiler error
}
It can
extend other interfaces which do not have any abstract method and only have the
default, static, another class is overridden, and normal methods. For eg:
interface Parent {
public void parentMethod(){
System.out.println("Hello");
}
}
@FunctionalInterface
interface Child extends Parent
{
public int childMethod();
}
What is
the default method, and why is it required?
A method
in the interface that has a predefined body is known as the default method. It
uses the keyword default. default methods were introduced in Java 8 to have
'Backward Compatibility in case JDK modifies any interfaces. In case a new
abstract method is added to the interface, all classes implementing the
interface will break and will have to implement the new method. With default
methods, there will not be any impact on the interface implementing classes.
default methods can be overridden if needed in the implementation. Also, it
does not qualify as synchronized or final.
@FunctionalInterface
// Annotation is optional
public interface Foo() {
//
Default Method - Optional can be 0 or more
public default String HelloWorld()
{
return "Hello World";
}
//
Single Abstract Method
public void bar();
}
What
are static methods in Interfaces?
Static
methods, which contains method implementation is owned by the interface and is
invoked using the name of the interface, it is suitable for defining the
utility methods and cannot be overridden.
What
are some standard Java pre-defined functional interfaces?
Some of
the famous pre-defined functional interfaces from previous Java versions are
Runnable, Callable, Comparator, and Comparable. While Java 8 introduces
functional interfaces like Supplier, Consumer, Predicate, etc. Please refer to
the java.util.function doc for other predefined functional interfaces and its
description introduced in Java 8.
Runnable: use to execute the instances
of a class over another thread with no arguments and no return value.
Callable: use to execute the instances
of a class over another thread with no arguments and it either returns a value
or throws an exception.
Comparator: use to sort different objects
in a user-defined order
Comparable: use to sort objects in the natural sort order.
What
are the various categories of pre-defined function interfaces?
Function<T,R>: Represents a function that takes an argument of type T
and produces a result of type R
Ex: Function<Integer, String> intToString = num -> "Number: " + num; System.out.println(intToString.apply(10)); // "Number: 10"
Predicate<R>: To perform a test and return
a Boolean value.
Ex: Predicate<String> isNotEmpty = str -> !str.isEmpty(); System.out.println(isNotEmpty.test("Hello")); // true System.out.println(isNotEmpty.test("")); // false
Consumer: Represents an operation that accepts a single input argument and returns no result.
Ex: Consumer<String> printUpperCase = str -> System.out.println(str.toUpperCase()); printUpperCase.accept("hello"); // "HELLO"
Supplier: Represents a supplier of results. It provides a result of type T
and does not take any arguments.
Ex: Supplier<String> getGreeting = () -> "Hello, World!"; System.out.println(getGreeting.get()); // "Hello, World!"
Operator: Perform a reduction type operation that accepts the same input types
Summary
Predicate<T>
: Tests a condition.Function<T, R>
: Transforms an input to an output.Consumer<T>
: Accepts an input and performs an action without returning a result.Supplier<T>
: Provides a result without any input.BinaryOperator<T>
: Operates on two operands of the same type.UnaryOperator<T>
: Operates on a single operand of the same type.
What
are the advantages of using the Optional class?
The
optional keyword is used in Java 8 to avoid the occurrence of the
NullPointerException.
It
encapsulates optional values, i.e., null or not-null values, which helps in
avoiding null checks, which results in better, readable, and robust code It
acts as a wrapper around the object and returns an object instead of a value,
which can be used to avoid run-time NullPointerExceptions.
What
are Java 8 streams?
A stream
is an abstraction to express data processing queries in a declarative
way.
Stream
pipelining is a concept that is implemented in Java 8 so that users can chain
more than one operation at a time. This works on the principle of splitting the
operation into two categories:
- Intermediate
operations:
Return the instance of the stream when running
- Terminal operations: Used to terminate the operation and return the final value
When is
an ideal situation to use the Stream API in Java 8?
The
Stream API in Java 8 can be effectively used if the Java project calls for the
following operations:
- Perform
database operations
- Execute
operations lazily
- Write
functional-style programming
- Perform
parallel processing
- Use
pipeline operations
- Use internal iteration
What are the main components of a Stream?
Components
of the stream are:
- A
data source
- Set
of Intermediate Operations to process the data source
- Single Terminal Operation that produces the result
What
are the sources of data objects a Stream can process?
A
Stream can process the following data:
- A
collection of an Array.
- An
I/O channel or an input device.
- A
reactive source (e.g., comments in social media or tweets/re-tweets)
- A
stream generator function or a static factory.
What
are Intermediate and Terminal operations?
Intermediate
Operations:
- Process
the stream elements.
- Typically
transforms a stream into another stream.
- Are
lazy, i.e., not executed till a terminal operation is invoked.
- Does
internal iteration of all source elements.
- Any
number of operations can be chained in the processing pipeline.
- Operations
are applied as per the defined order.
- Intermediate
operations are mostly lambda functions.
Terminal
Operations:
- Kick-starts
the Stream pipeline.
- used
to collect the processed Stream data.
int count = Stream.of(1, 2, 3, 4, 5)
.filter(i
-> i <4) // Intermediate Operation filter
.count(); // Terminal Operation count
What
are the most commonly used Intermediate operations?
Filter(Predicate<T>) - Allows selective processing
of Stream elements. It returns elements that are satisfying the supplied
condition by the predicate.
map(Funtion<T,
R>) -
Returns a new Stream, transforming each of the elements by applying the
supplied mapper function.= sorted() - Sorts the input elements and then passes
them to the next stage.
distinct() - Only pass on elements to
the next stage, not passed yet.
limit(long
maxsize) -
Limit the stream size to maxsize.
skip(long
start) - Skip
the initial elements till the start.
peek(Consumer) - Apply a consumer without
modification to the stream.
flatMap(mapper) - Transform each element to a
stream of its constituent elements and flatten all the streams into a single
stream.
What is
the stateful intermediate operation? Give some examples of stateful
intermediate operations.
To
complete some of the intermediate operations, some state is to be maintained,
and such intermediate operations are called stateful intermediate operations.
Parallel execution of these types of operations is complex.
For Eg:
sorted() , distinct() , limit() , skip() etc.
Sending
data elements to further steps in the pipeline stops till all the data is
sorted for sorted() and stream data elements are stored in temporary data
structures.
What is
the most common type of Terminal operations?
- collect() - Collects single
result from all elements of the stream sequence.
- reduce() - Produces a single
result from all elements of the stream sequence
- count()
- Returns the number of elements on the stream.
- min()
- Returns the min element from the stream.
- max()
- Returns the max element from the stream.
- Search/Query operations
- anyMatch()
, noneMatch() , allMatch() , ... - Short-circuiting operations.
- Takes
a Predicate as input for the match condition.
- Stream
processing will be stopped, as and when the result can be determined.
- Iterative operations
- forEach()
- Useful to do something with each of the Stream elements. It accepts a
consumer.
- forEachOrdered()
- It is helpful to maintain order in parallel streams.
What is
the difference between findFirst() and findAny()?
findFirst() |
findAny() |
Returns the first element in the Stream |
Return any element from the Stream |
Deterministic in nature |
Non-deterministic in nature |
How are
Collections different from Stream?
Collections
are the source for the Stream. Java 8 collection API is enhanced with the
default methods returning Stream<T> from the collections.
Collections |
Streams |
Data structure holds all the data
elements |
No data is stored. Have the capacity to
process an infinite number of elements on demand |
External Iteration |
Internal Iteration |
Can be processed any number of times |
Traversed only once |
Elements are easy to access |
No direct way of accessing specific
elements |
Is a data store |
Is an API to process the data |
What
are Map and FlatMap stream operations?
Map and FlatMap are regarded as the stream and intermediate stream operations which accepts a function. It also helps in applying the given function to the rest of the elements.
What
were the issues that were fixed with the new Date and Time API of Java 8?
With the
older versions of Java, java.util.The date was mutable. This means it has
absolutely no thread safety.
Also, java.text.SimpleDateFormat was not thread-safe in the older versions. The older Date and Time API was difficult to understand for programmers in terms of readability too.
What is
the feature of the new Date and Time API in Java 8?
- Immutable
classes and Thread-safe
- Timezone
support
- Fluent
methods for object creation and arithmetic
- Addresses
I18N issue for earlier APIs
- Influenced
by popular joda-time package
- All
packages are based on the ISO-8601 calendar system
What
are the important packages for the new Data and Time API?
- java.time
- dates
- times
- Instants
- durations
- time-zones
- periods
- Java.time.format
- Java.time.temporal
- java.time.zone
Explain
with example, LocalDate, LocalTime, and LocalDateTime APIs.
LocalDate
- Date
with no time component
- Default
format - yyyy-MM-dd (2020-02-20)
- LocalDate
today = LocalDate.now(); // gives today’s date
- LocalDate
aDate = LocalDate.of(2011, 12, 30); //(year, month, date)
LocalTime
- Time
with no date with nanosecond precision
- Default
format - hh:mm:ss:zzz (12:06:03.015) nanosecond is optional
- LocalTime
now = LocalTime.now(); // gives time now
- LocalTime
aTime2 = LocalTime.of(18, 20, 30); // (hours, min, sec)
LocalDateTime
- Holds
both Date and Time
- Default
format - yyyy-MM-dd-HH-mm-ss.zzz (2020-02-20T12:06:03.015)
- LocalDateTime
timestamp = LocalDateTime.now(); // gives timestamp now
- //(year,
month, date, hours, min, sec)
- LocalDateTime
dt1 = LocalDateTime.of(2011, 12, 30, 18, 20, 30);
Define
Nashorn in Java 8
Nashorn is
a JavaScript processing engine that is bundled with Java 8. It provides better
compliance with ECMA (European Computer Manufacturers Association) normalized
JavaScript specifications and better performance at run-time than older
versions.
What is
the use of JJS in Java 8?
As part of
Java 8, JJS is a command-line tool that helps to execute the JavaScript code in
the console. Below is the example of CLI commands:
JAVA>jjs
jjs> print("Hello, Java 8 - I am the new JJS!")
Hello, Java 8 - I am the new JJS!
jjs> quit()
>>
No comments:
Post a Comment