Java 8 Important
Features-
Functional Interface-
A Functional Interface is an
interface, which contains one and only one abstract method.
@FunctionalInterface
public interface FuncInterface {
public void welcome(String name);
}
public interface FuncInterface {
public void welcome(String name);
}
public class
TestMain {
public static void
main(String[] args) {
FuncInterface
funcInterface = (name) ->
System.out.println("Welcome
! " + name);
funcInterface.welcome("Manoj");
}
}
BiConsumer Functional
Interface
import java.util.function.BiConsumer;
public class TestMain {
public static void main(String[] args) {
BiConsumer<String, String> consumer = (a, b) -> {
System.out.println(a + b);
};
consumer.accept("Welcome", " MK Study Journal");
}
}
public class TestMain {
public static void main(String[] args) {
BiConsumer<String, String> consumer = (a, b) -> {
System.out.println(a + b);
};
consumer.accept("Welcome", " MK Study Journal");
}
}
BiFunction Functional
Interface
import java.util.function.BiFunction;
public class TestMain {
public static void main(String[] args) {
BiFunction<String, String, String> biFunction = (a, b) -> {
return a + b;
};
System.out.println(biFunction.apply("Welcome", " MK Study Journal"));
}
}
public class TestMain {
public static void main(String[] args) {
BiFunction<String, String, String> biFunction = (a, b) -> {
return a + b;
};
System.out.println(biFunction.apply("Welcome", " MK Study Journal"));
}
}
BinaryOperator Functional
Interface
import java.util.function.BinaryOperator;
public class TestMain {
public static void main(String[] args) {
BinaryOperator<Integer> findMaxBinOperator = BinaryOperator
.maxBy( (a, b) -> (a > b) ? 1 : ((a == b) ? 0 : -1));
System.out.println(findMaxBinOperator.apply(21, 17));
}
}
public class TestMain {
public static void main(String[] args) {
BinaryOperator<Integer> findMaxBinOperator = BinaryOperator
.maxBy( (a, b) -> (a > b) ? 1 : ((a == b) ? 0 : -1));
System.out.println(findMaxBinOperator.apply(21, 17));
}
}
Predicate and Bipredicate
functional interface-
import java.util.function.BiPredicate;
import java.util.function.Predicate;
public class TestMain {
public static void main(String[] args) {
Predicate<Integer> pr = a -> (a > 10); //will check given number is greater than 10
System.out.println(pr.test(9)); //false
System.out.println(pr.test(13)); //true
BiPredicate<Integer, Integer> biPr = (a , b) -> (a > b);
System.out.println(biPr.test(9, 13)); //false
System.out.println(biPr.test(13, 9)); //true
}
}
import java.util.function.Predicate;
public class TestMain {
public static void main(String[] args) {
Predicate<Integer> pr = a -> (a > 10); //will check given number is greater than 10
System.out.println(pr.test(9)); //false
System.out.println(pr.test(13)); //true
BiPredicate<Integer, Integer> biPr = (a , b) -> (a > b);
System.out.println(biPr.test(9, 13)); //false
System.out.println(biPr.test(13, 9)); //true
}
}
UnaryOperator and Suppiler functions-
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
public class TestMain {
public static void main(String[] args) {
UnaryOperator<Integer> unaryOperatorSquare = a -> (a*a);
System.out.println(unaryOperatorSquare.apply(10));
Supplier<Long> randomValue = () -> System.nanoTime();
System.out.println(randomValue.get());
}
}
import java.util.function.UnaryOperator;
public class TestMain {
public static void main(String[] args) {
UnaryOperator<Integer> unaryOperatorSquare = a -> (a*a);
System.out.println(unaryOperatorSquare.apply(10));
Supplier<Long> randomValue = () -> System.nanoTime();
System.out.println(randomValue.get());
}
}
Lambda Expression
Structure of Lambda
Expressions
1) A lambda expression can have zero, one or more
the one parameters.
2) The type of the parameters can be explicitly
declared or it can be inferred from the context.
3) Parameters are enclosed in parentheses and
separated by commas
4) Empty parentheses are used to represent an
empty set of parameters. e.g. () -> 42
5) When there is a single parameter, if its type
is inferred, it is not mandatory to use parentheses. e.g. a -> return a*a
6) The body of the lambda expressions can contain
zero, one or more statements.
7) If body of lambda expression has single
statement curly brackets are not mandatory and the return type of the anonymous
function is the same as that of the body expression.
8) When there is more than one statement in body
than these must be enclosed in curly brackets (a code block) and the return
type of the anonymous function is the same as the type of the value returned
within the code block, or void if nothing is returned.
Here’s the syntax:
(argtype arg...) ->
{return some expression... probably using these arguments}
Code Snippet –
Runnable java8Runner = () -> {System.out.println("I am running"); };
Generic Type changes
and improvements
The methods for
instance using a generic collection need not specify genric types
Code Snippet –
In java 7 –
final List<Boolean> bools = Arrays.asList(true);
final List<Character> string = bools.stream().<Character>map(x -> x ? ’a’: 'b')
.collect(Collectors.<Character>toList());
In java 8 –
final List<Boolean> bools1 = Arrays.asList(true);
final List<Character> string1 = bools.stream().map(x -> x ? ’a’: 'b')
.collect (Collectors.toList());
forEach() method in Iterable
interface-
This is an improved
version of forEach loop, with this method of Iterable interface all the
implementing class can iterate easily, refer below code snippet-
public class
TestMain {
public static void
main(String[] args) {
List<String> list = Arrays.asList("1","2","3");
list.forEach(str ->
System.out.println(str));
}
}
Stream Collection
Types (java.util.stream)
Stream can process
data in a declarative way
Streams support Aggregate
Operations like filter, map, reduce, find, match, sort etc.
These operations can be executed in series or in parallel.
Collection interface
has been extended with stream() and parallelStream() default
methods to get the Stream for sequential and parallel execution
Code Snippet –
List<String> list = Arrays.asList("a1", "a2", "a3", "a4", "a5");
list.stream().filter(s -> s.endsWith("5")) .map(String::toUpperCase) .sorted() .forEach(System.out::println);
Default and static
method in interface-
public interface DefaultMethInterface {
public default void welcome(){
System.out.println("welcome");
}
public static void welcomeStatic(){
System.out.println("static welcome");
}
}
public default void welcome(){
System.out.println("welcome");
}
public static void welcomeStatic(){
System.out.println("static welcome");
}
}
Optional class -
It is defined in java.util
package.
It is used to represent
optional values that is either exist or not exist. It contain either one value
or zero value.
It is a bounded collection
that is it contains at most one element only. It is an alternative to “null”
value.
Date Time API
The existing classes such as
java.util.Date and SimpleDateFormatter aren’t thread-safe.
Java 8 under the package
java.time introduced a new date-time API,
1)
Local : Simplified date-time
API with no complexity of timezone handling.
2)
Zoned : Specialized date-time
API to deal with various timezones.
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
public class TestMain {
public static void main(String[] args) {
LocalDate date = LocalDate.now();
System.out.println(" Current date ::" + date);
LocalDate nextMonday = date.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
System.out.println("Date on upcoming monday : " + nextMonday);
Period period = Period.between(nextMonday, date);
System.out.println("Gap on next monday "+period);
System.out.println("Current time :: " + LocalTime.now());
Duration fiveHours = Duration.ofHours(2);
LocalTime time = LocalTime.now().plus(fiveHours);
System.out.println("Time after 2 hours :: " + time);
LocalDateTime current = LocalDateTime.now();
System.out.println("Current date-time : " +current);
DateTimeFormatter format = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");
System.out.println("Formatted Date " +current.format(format));
}
}
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
public class TestMain {
public static void main(String[] args) {
LocalDate date = LocalDate.now();
System.out.println(" Current date ::" + date);
LocalDate nextMonday = date.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
System.out.println("Date on upcoming monday : " + nextMonday);
Period period = Period.between(nextMonday, date);
System.out.println("Gap on next monday "+period);
System.out.println("Current time :: " + LocalTime.now());
Duration fiveHours = Duration.ofHours(2);
LocalTime time = LocalTime.now().plus(fiveHours);
System.out.println("Time after 2 hours :: " + time);
LocalDateTime current = LocalDateTime.now();
System.out.println("Current date-time : " +current);
DateTimeFormatter format = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");
System.out.println("Formatted Date " +current.format(format));
}
}
Map vs FlatMap
map and flatMap are
intermediate stream operations that receive a function and apply this function
to all elements of a stream
The map() method wraps the
underlying sequence in a Stream instance, whereas the flatMap() method allows
avoiding nested Stream<Stream<R>> structure.
map() is used to transform a
single stream of values while flatMap() is used to transform stream of stream
values. Refer below code snippet-
import java.util.*; import java.util.stream.Collectors; public class TestMain { public static void main(String[] args) { List<String> list1 = Arrays.asList("Hello", "Friends"); List<String> list2 = Arrays.asList("Welcome", "in"); List<String> list3 = Arrays.asList("MK", "Study", "Journal"); //map will transform string in a list to uppercase. List<String> list1Upper = list1.stream() .map(String::toUpperCase) .collect(Collectors.toList()); System.out.println(" map : " + list1Upper); List<List<String>> listOfLists = Arrays.asList(list1, list2, list3); System.out.println("Before : " + listOfLists); //flat map is used to transform the list of list List<String> flatList = listOfLists.stream() .flatMap(list -> list.stream()) .collect(Collectors.toList()); System.out.println("After : " + flatList); } }
Output-
map : [HELLO,
FRIENDS]
Before : [[Hello,
Friends], [Welcome, in], [MK, Study, Journal]]
After : [Hello, Friends, Welcome, in, MK, Study,
Journal]
Improvement in
Concurrent API-
New interface- CompletableFuture.AsynchronousCompletionTask
A marker interface
identifying asynchronous tasks produced by async methods. This may be
useful for monitoring, debugging, and tracking asynchronous activities.
Various aggregate operation
are added base on stream and lambda expression like-
ConcurrentHashMap have
several new methods like -forEach, forEachKey, forEachValue, ,forEachEntry
etc
PermGen space is
removed and Introduces Metaspace memory model-
PermGen space is completely
removed in JAVA8, draw back of PermGen space-
Fixed size and it was
difficult to tune.
Due to fix size it gives
error - java.lang.OutOfMemoryError: PermGen error.
Benefits of Metaspace-
class metadata are allocated
out of native memory.
Flag MaxMetaspaceSize is used
to limit the amount of
native memory used for class metadata. If you don’t specify this flag, the
Metaspace will dynamically re-size depending of the application
demand at runtime.
Refer our youtube channel for latest videos - https://www.youtube.com/watch?v=7yb1IBb-XlU&t=496s
Good source for java 8 topics.
ReplyDeletePlease provide some real use cases for java 8 concurrent api.
Great blog
ReplyDeleteNice information, very usefull thanks
ReplyDeletethanks
ReplyDelete