Monday, 12 August 2019

What are the new features in Java 8?

“Java Standard Edition 8 (Java SE 8)” is released on 18th March 2014. Along with the Java SE 8 platform, the product that implements the platform, “Java SE Development Kit 8 (JDK 8)” and “Java SE Run time Environment 8 (JRE 8)” is also released and available for download.

Java SE 8 is one of the most feature packed release in the Java history. Here let us go through the highlights of the core features of Java 8. Following list is a highlight of important features, there are other minor enhancements, security features, bug fixes are available as part of Java 8.

1) Lambda Expressions

Lambda expressions gives the ability to pass a functionality as a method argument. Lambda expression help us reduce the code clutter in using a single method class. For example, when we have to associate an action button click to a functionality, then lambda expressions will make the code look neat and compact.

2) Pipelines and Streams

Pipelines and streams enrich the Java collections framework. Sequence of aggregate operations is a pipeline. Stream is used to propagate elements from a source through a pipeline. It is a sequence of elements. Pipeline and streams will make our task easier in accessing the elements from collections and applying operations on it.

3) Date and Time API

Pre Java 8, date and time related operations are little bit cumbersome. JSR 310: Date and Time API give us a brand new package java.time package. This is a well thought package. It contains a best list of utility methods used for regular operations. This will help in handling date and time operations in an easier way.

4) Default Methods

Default methods gives the ability to add default implementation for methods in an interface. This is a rocking feature of Java 8. When we implement an interface, if we did not provide implementation for a method, then the default method will be used in that place. This will help in maintaining backward compatibility in applications, we can add a method to an interface without breaking its implementations.

5) Type Annotations

Before Java 8 Java annotations can be applied to type declarations. From this Java 8 release onwards, annotations can be applied to type use. Annotations can be applied wherever a type is used like in new instance creates, exception throws clause etc. This will help to enforce stronger type checks and using this feature we can come up with a type checking framework itself.

6) Nashorn JavaScript Engine

Nashorn is a brand new JavaScript engine provided along with the Java 8 release. Using this we can develop standalone JavaScript applications in Java. Pre Java 8, we got JDK with a JavaScript engine based on Rhino. It is a developed from scratch. It will provide better compatibility with ECMA normalized JavaScript specification and better performance than Rhino.

7) Concurrent Accumulators

java.util.concurrent.atomic package is getting additional classes as part of Java 8 release. These will help to sum values from across multiple threads.

8) Parallel operations

Iterating over a collection can be done in parallel using the aggregate operations easily. Pre Java 8 Iterators are used to parse the elements of a collection one by on explicitly. Now that can be done in parallel internally with the use of streams and aggregate operations. We can create multiple substreams and those substreams can be processed internally in parallel and then the results be combined. For this to be effective, we need to have multiple cores and data volume.

9) PermGen Space Removed

The PermGen space is removed from Java 8 and instead we have MetaSpace introduced. One of the most dreaded error, “java.lang.OutOfMemoryError: PermGen error” will no longer be seen from Java 8. Nice thing is that the MetaSpace default is unlimited and that the system memory itself becomes the memory.

10)TLS SNI

Server Name Indentification (SNI) is an extension of the TLS protocol used for identifying the certificate to serve based on the hostname specified by the client. This enables a server to have virtual host over HTTPS. The same IP address can be used for multiple hosts and their respective different security certificates.


------------------------------------------------------------------------------------------------------------

Java 8 Lambda Expressions
=========================

Lambda expressions, Functional interfaces and Stream API – these three features of Java 8 has turned Java programming into new style of programming called functional-style programming. Java is still an object-oriented programming language, but from Java 8, with the introduction of new features, most of the programming is done keeping functions in mind rather than objects

1) Definition

Java 8 Lambda Expressions can be defined as methods without names i.e anonymous functions. Like methods, they can have parameters, a body, a return type and possible list of exceptions that can be thrown. But unlike methods, neither they have names nor they are associated with any particular class.

2) Lambda Syntax

(Parameters) -> Expression

OR

(Parameters) -> { Statements }

Lambda syntax consist of three parts – list of parameters, an arrow mark and a body. The body of a lambda can be an expression or a set of statements. If it is set of statements, they must be enclosed within curly braces { }. Return type and possible list of exceptions that can be thrown are not explicitly mentioned in a lambda. They are implicitly applied.

3) Where To Use Lambda Expressions?

Lambda expressions are used where an instance of functional interface is expected. Functional interface is an interface which has only one abstract method. Functional interfaces can have any number of default methods. But, they must have only one abstract method. Comparator, Runnable AndActionListener are some examples of functional interfaces.

import java.util.function;

@FunctionalInterface
public interface Comparator
{
    int compare(T o1, T o2);       //Only one abstract method
}

@FunctionalInterface
public interface Runnable
{
    public abstract void run();   //Only one abstract method
}

@FunctionalInterface
public interface ActionListener extends EventListener
{
    public void actionPerformed(ActionEvent e);  //Only One abstract method
}


Before Java 8, anonymous inner classes are used to implement functional interfaces. After Java 8, you can use lambda expressions to implement functional interfaces.

4) How To Use Lambda Expressions?

Lambda expressions are used to implement functional interfaces. Before Java 8, anonymous inner classes are used to implement functional interfaces.

------------------------------

Before Java 8:

Comparator<Student> idComparator = new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                return s1.getID()-s2.getID();
            }
        };
After Java 8 : Implementation of Comaparator interface using lambda expressions

1
Comparator<Student> idComparator = (Student s1, Student s2) -> s1.getID()-s2.getID();

-----------------------------

Before Java 8 :

Runnable r = new Runnable() { 
            @Override
            public void run() {
                System.out.println("Runnable Implementation Using Anonymous Inner Class");
            }
        };
After Java 8 : Implementation of Runnable interface using lambda expressions

Runnable r = () -> System.out.println("Runnable Implementation Using Lambda Expressions");

----------------------------

Before Java 8 : Implementation Of ActionListener interface using anonymous inner class

Label label = new Label();
       
Button button = new Button("Send");
       
button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        label.setText("Sent");
    }
});


After Java 8 : Implementation of ActionListener interface using lambda expressions


Label label = new Label();
       
Button button = new Button("Send");
       
button.addActionListener((ActionEvent e) -> label.setText("Sent..."));


5) Lambdas As Inline Implementation Of Functional Interfaces

From the above examples, you can notice that lambdas instantiate functional interfaces and implement their abstract method in a single line. Before Java 8, anonymous inner classes are used for this purpose. But, they create lots of verbosity i.e you end up writing more lines of code than actually needed.


6) Signature Of Lambda Expressions

The signature of lambda expressions can be derived from the signature of abstract method of functional interface.

For example,

run() method of Runnable interface accepts nothing and returns nothing. Then signature of lambda expression implementing Runnable interface will be () -> void.

actionPerformed() method of ActionListener interface takes one argument of type ActionEvent and returns void. Then signature of lambda expression for implementing ActionListener interface will be (ActionEvent) -> void.

compare() method of Comparator interface takes two arguments of type Object and returns int. Then signature of lambda expression for implementing Comparator interface will be (Object, Object) -> int.

7) Type Checking

The type of a variable or a parameter to which lambda expression is assigned or passed as an argument is called target type.

For example, if you are assigning a lambda to a Runnable type then its target type is Runnable. If you are passing a lambda to a method which takes ActionListener as an argument, then its target type is ActionListener.

Compiler uses this target type to check the type of parameters and return type of a lambda expression. For example,

1
Runnable r = () -> System.out.println("Runnable Implementation Using Lambda Expressions");
In the above code, target type of lambda expression is Runnable. Compiler uses run() method of Runnable interface to check the type of parameters and return type of lambda expression.

1
button.addActionListener((ActionEvent e) -> label.setText("Sent..."));
In the above code, target type of lambda expression is ActionListener. Compiler uses actionPerformed() method of ActionListener to check the type of parameters and return type of lambda expression.


8) Use Of Local Variables Inside Lambda Expression

You can use local variables inside a lambda expression just like anonymous inner classes provided they must be final or effectively final.

For example, the following code will show error because you are re-assigning new Label() to label.

Label label = new Label();
       
Button button = new Button("Send");
       
button.addActionListener((ActionEvent e) -> label.setText("Sent..."));      //Compile Time Error
       
label = new Label();

9) Benefits Of Lambda Expressions

Lambda expressions let you to write more clear, concise and flexible code.
Lambda expressions removes verbosity and repetition of code.

10) Valid Lambda Expressions With Description
-------------------------------------------------------------------------------------------------
() -> System.out.println("Hello Nishant");    --- takes nothing return nothing

(int a) -> a*a                                --- takes int return int

(String s1,String s2) -> {                    --- takes 2 string and return nothing
   System.out.println("Hello");
   System.out.println("Nishant");
   }

(double d) -> d                               --- takes double and return double

() -> {}                                      --- takes nothing return nothing (it has empty body)
--------------------------------------------------------------------------------------------------






******* How To Use Java 8 Functional Interfaces In Real Time?
=============================================================




Let’s define Student class like below. We will be using this class in the subsequent examples.

class Student
{
    int id;
    String name;
    double percentage;
    String specialization;
    // parameterized constructor
    public Student(int id, String name, double percentage, String specialization)
    {
        this.id = id;
        this.name = name;
        this.percentage = percentage;
        this.specialization = specialization;
    }
    // applying getters
    public int getId() {
        return id;
    }
    public String getName() {
        return name;
    }
    public double getPercentage() {
        return percentage;
    }
    public String getSpecialization() {
        return specialization;
    }

    @Override
    public String toString()
    {
        return id+"-"+name+"-"+percentage+"-"+specialization;
    }
}


Now, Let's create listOfStudents be the list of 10 students.

List<Student> listOfStudents = new ArrayList<Student>();

listOfStudents.add(new Student(111, "John", 81.0, "Mathematics"));
listOfStudents.add(new Student(222, "Harsha", 79.5, "History"));
listOfStudents.add(new Student(333, "Ruth", 87.2, "Computers"));
listOfStudents.add(new Student(444, "Aroma", 63.2, "Mathematics"));
listOfStudents.add(new Student(555, "Zade", 83.5, "Computers"));
listOfStudents.add(new Student(666, "Xing", 58.5, "Geography"));
listOfStudents.add(new Student(777, "Richards", 72.6, "Banking"));
listOfStudents.add(new Student(888, "Sunil", 86.7, "History"));
listOfStudents.add(new Student(999, "Jordan", 58.6, "Finance"));       
listOfStudents.add(new Student(101010, "Chris", 89.8, "Computers"));


Now, see how to use 4 important functional interfaces – Predicate, Consumer, Function and Supplier using above listOfStudents.

a) Predicate – Tests an object

Predicate represents an operation which takes an argument T and returns a boolean. Use this functional interface, if you want to define a lambda expression which performs some test on an argument and returns true or false depending upon outcome of the test.

For example,

Imagine an operation where you want only a list of “Mathematics” students from the above listOfStudents. Let’s see how to do it using Predicate.
----------------------------------------------------------------

Predicate<Student> mathematicsPredicate = (Student student) -> student.getSpecialization().equals("Mathematics");       
List<Student> mathematicsStudents = new ArrayList<Student>();
for (Student student : listOfStudents)
{
    if (mathematicsPredicate.test(student))
    {
        mathematicsStudents.add(student);
    }
}


b) Consumer – Consumes an object

Consumer represents an operation which takes an argument and returns nothing. Use this functional interface If you want to compose a lambda expression which performs some operations on an object.

For example, displaying all students with their percentage.

Lambda expression implementing Consumer : Displaying all students with their percentage
---------------------------------------------------------------------------------------

Consumer<Student> percentageConsumer = (Student student) -> {
        System.out.println(student.getName()+" : "+student.getPercentage());
    };       
for (Student student : listOfStudents)
{
    percentageConsumer.accept(student);
}


c) Function – Applies to an object

Function represents an operation which takes an argument of type T and returns a result of type R. Use this functional interface if you want to extract some data from an existing data.

For example, extracting only the names from listOfStudents.
-----------------------------------------------------------

Function<Student, String> nameFunction = (Student Student) -> Student.getName();
List<String> studentNames = new ArrayList<String>();       
for (Student student : listOfStudents)
{
    studentNames.add(nameFunction.apply(student));
}


d) Supplier – Supplies the objects

Supplier represents an operation which takes no argument and returns the results of type R. Use this functional interface when you want to create new objects.

Lambda expression implementing Supplier : Creating a new Student
----------------------------------------------------------------

Supplier<Student> studentSupplier = () -> new Student(111111, "New Student", 92.9, "Java 8");
listOfStudents.add(studentSupplier.get());


5) Functional Interfaces Supporting Primitive Type

Java 8 has also introduced functional interfaces which support primitive types.
For example IntPredicate, DoublePredicate, LongConsumer etc… (See above table).

If an input or output is a primitive type then using these functional interfaces will enhance the performance of your code.
For example, if input to a Predicate is primitive type int then using intPredicate instead of Predicate will remove unnecessary boxing of input.






******* What is Java 8 Method References In Real Time?
======================================================




1) Definition

Java 8 method references are the shortened versions of lambda expressions calling a specific method.
Method references are the easiest way to refer a method than the lambdas calling a specific method.
Method references will enhance the readability of your code.

For example, lambda expression (Student s) -> s.getName()

which is calling a method getName() of Student class can be shortened as Student::getName using Java 8 method references.

2) Syntax

a) Method reference to static method :

ClassName::MethodName

Use this syntax when you are referring to a static method.

ex : Integer::parseInt, Math::max

b) Method reference to instance method of an existing object :

ReferenceVariable::MethodName

Use this syntax when you are referring to an instance method of already existing object.

ex : s::getName

where ‘s’ is a reference variable referring to Student object which already exist.

c) Method reference to instance method of non-existing object :

ClassName::MethodName

Use this syntax when you are referring to an instance method by passing reference variables as an argument.

ex : (Student s) -> s.getName() can be written as Student::getName


3) Constructor References
You can also refer to the constructor of a class same as method references. Syntax for referring to constructor is,

ClassName::new

Ex : Student::new

Following : javaconceptoftheday



************ What is Java 8 Interface Changes : Default Methods And Static Methods




It has been a tough task for Java API developers to add new methods to current interfaces. Because, even if you add a single abstract method to an interface, all existing implementations of that interface have to be updated with implementation of new method. What if there exist hundreds or thousands of implementations of an interface? Even worse, What if you don’t have control over all of those implementations? To overcome such overhead, new features are introduced to interfaces from Java 8. They are default methods and static methods. In this article, we will see these new Java 8 Interface Changes.


From Java 8, interfaces can also have concrete methods i.e methods with body along with abstract methods. This is the major change introduced to interfaces in Java 8 to help Java API developers to update and maintain the interfaces. The interfaces can have concrete methods either in the form of default methods or static methods.

A) Default Methods
------------------

1) Definition With Example

Default methods of an interface are the concrete methods i.e methods with body for which implementing classes need not to give implementation. They inherit default implementation. Default methods start with the modifier default.

interface InterfaceWithDefaultMethod
{
    void abstractMethod();           //Abstract Method
   
    default void defaultMethod()
    {
        System.out.println("It is a default method");
    }
}

class AnyClass implements InterfaceWithDefaultMethod
{
    @Override
    public void abstractMethod()
    {
        System.out.println("Abstract Method implemented");
    }
   
    //No need to implement defaultMethod()
}


2) Why Default Methods?

Default methods are introduced to add extra features to current interfaces without disrupting their existing implementations.
For example, stream() is a default method which is added to Collection interface in Java 8.

If stream() would have been added as abstract method, then all classes implementing Collection interface must have implemented stream() method which may have irritated existing users.

Thanks to Java 8 default method feature, now it is a default method, all implementations of Collection interface inherit default implementation of stream() method.


3) Three Rules To Solve Diamond Problem

In Java, a class can extend only one class but can implement multiple interfaces. With the introduction of default methods, it is possible that your class inherit multiple methods with same signature. In such scenarios, to solve the conflict, Java 8 specifies 3 rules to follow.

Rule 1 : Select classes over interfaces

If your class inherit multiple methods with same signature then a method from super class is selected (Remember a class can inherit only one class).


interface InterfaceOne
{
    default void anyMethod()
    {
        System.out.println("Hi... From Interface One");
    }
}

interface InterfaceTwo extends InterfaceOne
{
    @Override
    default void anyMethod()
    {
        System.out.println("Hi... From Interface Two");
    }
}

class ClassOne implements InterfaceOne, InterfaceTwo
{
    @Override
    public void anyMethod()
    {
        System.out.println("Hi... From Class One");
    }
}

public class MyClass extends ClassOne implements InterfaceOne, InterfaceTwo
{
    public static void main(String[] args)
    {
        new MyClass().anyMethod();
    }
}

output : Hi... From Class One


Rule 2 : Select most specific interfaces than general interfaces.

If your class doesn’t extend any class and inherit multiple methods with same signature from multiple interfaces which belong to same hierarchy, then a method from most specific interface is selected (If interface X extends Y then X is more specific than Y).

For example, In the below program, anyMethod() from InterfaceTwo is called.

interface InterfaceOne
{
    default void anyMethod()
    {
        System.out.println("Hi... From Interface One");
    }
}

interface InterfaceTwo extends InterfaceOne
{
    @Override
    default void anyMethod()
    {
        System.out.println("Hi... From Interface Two");
    }
}

public class MyClass implements InterfaceOne, InterfaceTwo
{
    public static void main(String[] args)
    {
        new MyClass().anyMethod();
    }
}

output : Hi... From Interface Two

Rule 3 : InterfaceName.super.methodName()

If your class doesn’t extend any class and inherit multiple methods with same signature from multiple interfaces which doesn’t belong to same hierarchy, then override that method and from within body explicitly call desired method as InterfaceName.super.methodName().

For example, in the below program, anyMethod() from InterfaceOne is called explicitly.

interface InterfaceOne
{
    default void anyMethod()
    {
        System.out.println("Hi... From Interface One");
    }
}

interface InterfaceTwo
{
    default void anyMethod()
    {
        System.out.println("Hi... From Interface Two");
    }
}

public class MyClass implements InterfaceOne, InterfaceTwo
{
    @Override
    public void anyMethod()
    {
        InterfaceOne.super.anyMethod();
    }
   
    public static void main(String[] args)
    {
        new MyClass().anyMethod();
    }
}

output : Hi... From Interface One



B) Static Methods
-----------------

1) Definition With Example

From Java 8, interfaces can also have static methods. Static methods are also concrete methods but they can’t be implemented.


interface InterfaceWithDefaultAndStaticMethod
{
    void abstractMethod();           //Abstract Method
   
    default void defaultMethod()
    {
        System.out.println("It is a default method");
    }
   
    static void staticMethod()
    {
        System.out.println("It is a static method");
    }
}

class AnyClass implements InterfaceWithDefaultAndStaticMethod
{
    @Override
    public void abstractMethod()
    {
        System.out.println("Abstract Method implemented");
    }
   
    //No need to implement defaultMethod()
   
    //Can't implement staticMethod()
}


2) Why Static Methods?
Do you know? Collection and Collections.

Collection is an interface and Collections is an utility class containing only static methods which operate on Collection objects.

Java API developers have followed this pattern of supplying an utility class along with an interface to perform basic operations on such objects. But from Java 8, they have break this pattern by introducing static methods to interfaces.

With the introduction of static methods to interface, such utility classes will disappear and methods to perform basic operations will be kept as static methods in interface itself.



**************** What is the difference between Collections And Streams In Java 8
================================================================

Collections are used to store and group the data in a particular data structure like List, Set or Map. But, streams are used to perform complex data processing operations like filtering, matching, mapping etc on stored data such as arrays, collections or I/O resources. That means, collections are mainly about data and streams are mainly about operations on data.

1) The Difference

//Usage of collections
       
//Collections are mainly used to store the data
       
//Here, names are stored as List
       
List<String> names = new ArrayList<>();
       
names.add("Charlie");
       
names.add("Douglas");
       
names.add("Sundaraman");
       
names.add("Charlie");
       
names.add("Yuki");
       
//Usage of streams
       
//Streams are mainly used to perform operations on data
       
//like selecting only unique names
       
names.stream().distinct().forEach(System.out::println);
       
//Output :
       
//Charlie
//Douglas
//Sundaraman
//Yuki



2) Data Modification

You can add to or remove elements from collections. But, you can’t add to or remove elements from streams. Stream consumes a source, performs operations on it and returns a result. They don’t modify even the source also.

List<String> names = Arrays.asList("Charlie", "Douglas", "Jacob");
       
//Adding elements to names
       
names.add("Sundaraman");
       
names.add("Yuki");
       
//Removing elements from names
       
names.remove(2);
       
//getting stream of unique names
       
Stream<String> uniqueNames = names.stream().distinct();
       
//You can't add or remove elements from stream
       
//There are no such methods in Stream


3) External Iteration Vs Internal Iteration

The main specialty of Java 8 Streams is that you need not to worry about iteration while using streams. Streams perform iteration internally behind the scene for you. You just have to mention the operations to be performed on a source.

On the other hand, you have to do the iteration externally over collections using loops.

List<String> names = new ArrayList<>();
               
names.add("Charlie");
               
names.add("Douglas");
               
names.add("Sundaraman");
               
names.add("Charlie");
               
names.add("Yuki");
       
//External iteration of collections
       
for (String name : names)
{
    System.out.println(name);
}
       
//Output :
       
//Charlie
//Douglas
//Sundaraman
//Charlie
//Yuki
       
//Internal iteration of streams. No for loops

names.stream().map(String::toUpperCase).forEach(System.out::println);
               
//Output :
               
//CHARLIE
//DOUGLAS
//SUNDARAMAN
//CHARLIE
//YUKI


4) Traversal

Streams are traversable only once. If you traverse the stream once, it is said to be consumed. To traverse it again, you have to get new stream from the source again. But, collections can be traversed multiple times.


List<Integer> numbers = Arrays.asList(4, 2, 8, 9, 5, 6, 7);
       
Stream<Integer> numbersGreaterThan5 = numbers.stream().filter(i -> i > 5);
       
//Traversing numbersGreaterThan5 stream first time
       
numbersGreaterThan5.forEach(System.out::println);
       
//Second time traversal will throw error
       
//Error : stream has already been operated upon or closed
       
numbersGreaterThan5.forEach(System.out::println);



5) Eager Construction Vs Lazy Construction


Collections are eagerly constructed i.e all the elements are computed at the beginning itself. But, streams are lazily constructed i.e intermediate operations are not evaluated until terminal operation is invoked.


List<Integer> numbers = Arrays.asList(4, 2, 8, 9, 5, 6, 7);
               
numbers.stream().filter(i -> i >= 5).limit(3).forEach(System.out::println);

//Here, not all numbers are evaluated.
//numbers are evaluated until 3 numbers >= 5 are found.
       
//Output :
       
//8
//9
//5


*************** What is the Difference Between Collections Vs Streams In Java :

Collections                                                 Streams
-----------------------------------------------------------------------------------------------------------------
Collections are mainly used to store and group the data. Streams are mainly used to perform operations on data.
You can add or remove elements from collections.         You can’t add or remove elements from streams.
Collections have to be iterated externally.                 Streams are internally iterated.
Collections can be traversed multiple times.             Streams are traversable only once.
Collections are eagerly constructed.                     Streams are lazily constructed.
Ex : List, Set, Map…                                     Ex : filtering, mapping, matching…
-----------------------------------------------------------------------------------------------------------------



Java 8 Stream in details
========================

1) What Are Streams?
Streams can be defined as a sequences of elements from a source which support data processing operations. You can treat streams as operations on data. You will get to know as you go through this article.

2) Why Streams?
Almost every Java application use Collections API to store and process the data. Despite being the most used Java API, it is not easy to write the code for even some common data processing operations like filtering, finding, matching, sorting, mapping etc using Collections API . So, there needed Next-Gen API to process the data. So Java API designers have come with Java 8 Streams API to write more complex data processing operations with much of ease.

3) Characteristics Of Java 8 Streams

3.1) Streams are not the data structures
Streams doesn’t store the data. You can’t add or remove elements from streams. Hence, they are not the data structures. They are the just operations on data.

3.2) Stream Consumes a data source
Stream consumes a source, performs operations on it and produces the result. Source may be a collection or an array or an I/O resource. Remember, stream doesn’t modify the source.

3.3) Intermediate And Terminal Operations

Most of the stream operations return another new stream and they can be chained together to form a pipeline of operations.

The operations which return stream themselves are called intermediate operations. For example – filter(), distinct(), sorted() etc.

The operations which return other than stream are called terminal operations. count(). min(), max() are some terminal operations.

3.4) Pipeline Of Operations

A pipeline of operations consists of three things – a source, one or more intermediate operations and a terminal operation. Pipe-lining of operations let you to write database-like queries on a data source. In the below example, int array is the source, filter() and distinct() are intermediate operations and forEach() is a terminal operation.

IntStream.of(new int[] {4, 7, 1, 8, 3, 9, 7}).filter((int i) -> i > 5).distinct().forEach(System.out::println);

3.5) Internal Iteration

Collections need to be iterated explicitly. i.e you have to write the code to iterate over collections. But, all stream operations do the iteration internally behind the scene for you. You need not to worry about iteration at all while writing the code using Java 8 Streams API.

3.6) Parallel Execution

To gain the performance while processing the large amount of data, you have to process it in parallel and use multi core architectures. Java 8 Streams can be processed in parallel without writing any multi threaded code. For example, to process the collections in parallel, you just use parallelStream() method instead of stream() method.

List<String> names = new ArrayList<>();
       
names.add("David");
       
names.add("Johnson");
       
names.add("Samontika");
       
names.add("Brijesh");
       
names.add("John");
       
//Normal Execution
       
names.stream().filter((String name) -> name.length() > 5).skip(2).forEach(System.out::println);
       
//Parallel Execution
       
names.parallelStream().filter((String name) -> name.length() > 5).skip(2).forEach(System.out::println);


3.7) Streams are lazily populated

All elements of a stream are not populated at a time. They are lazily populated as per demand because intermediate operations are not evaluated until terminal operation is invoked.

3.8) Streams are traversable only once

You can’t traverse the streams more than once just like iterators. If you traverse the stream first time, it is said to be consumed.

List<String> nameList = Arrays.asList("Dinesh", "Ross", "Kagiso", "Steyn");
       
Stream<String> stream = nameList.stream();
       
stream.forEach(System.out::println);
       
stream.forEach(System.out::println);   
       
//Error : stream has already been operated upon or closed


3.9) Short Circuiting Operations

Short circuiting operations are the operations which don’t need the whole stream to be processed to produce a result. For example – findFirst(), findAny(), limit() etc.







**********  What is the Differences Between Interface And Abstract Class After Java 8 :
==================================================================

1) Fields

Interface fields are public, static and final by default. Interfaces still don’t support non-static and non-final variables. Interfaces can only have public, static and final variables. On the other hand, abstract class can have static as well as non-static and final as well as non-final variables. They also support private and protected variables along with public variables.

2) Methods

After Java 8, an interface can have default and static methods along with abstract methods. Interfaces don’t support final methods. But, abstract classes support final as well as non-final methods and static as well as non-static methods along with abstract methods.

Also note that, only interfaces can have default methods. Abstract classes can’t have default methods.

3) Constructors

Interfaces can’t have constructors. Abstract classes can have any number of constructors.

4) Member’s Accessibility

All members of interfaces are public by default. Interfaces don’t support private and protected members. But, abstract classes support all type of members – private, protected and public members.

5) Multiple Inheritance

A class can extend only one abstract class, but can implement multiple interfaces. Thus, a class can inherit multiple properties from multiple sources only through interfaces, not through abstract classes.

interface anyInterface
{
    int i = 10;            //By default, interface fields are public, static and final
   
    void abstractMethod();          //Interface can have abstract method
   
    default void defaultMethod()
    {
        System.out.println("Interface can have default method");
    }
   
    static void staticMethod()
    {
        System.out.println("Interface can have static method");
    }
   
    //No constructors in an interface
   
    //No non-static and non-final variables in an interface
   
    //No private fields and methods in an interface
   
    //No protected fields and methods in an interface
   
    //No final methods in an interface
}

abstract class anyAbstractClass
{
    private int a;          //Abstract class can have private field
   
    protected int b;        //Abstract class can have protected field
   
    public int c;           //Abstract class can have public field
   
    static int d;           //Abstract class can have static field
   
    final int e = 10;       //Abstract class can have final field
   
    int f;                  //Abstract class can have non-static and non-final field
   
    public anyAbstractClass()
    {
        System.out.println("Abstract class can have constructors");
    }
     
    abstract void abstractmethod();    //Abstract class can have abstract method
   
    private static void staticMethod()
    {
        System.out.println("Abstract class can have private and static method");
    }
   
    public void nonStaticMethod()
    {
        System.out.println("Abstract class can have public and non-static method");
    }
   
    protected void protectedMethod()
    {
        System.out.println("Abstract class can have protected method");
    }
   
    final void finalMethod()
    {
        System.out.println("Abstract class can have final method");
    }
   
    //No default method in an abstract class
}




https://javaconceptoftheday.com/java-8-streams-beginners-guide/

https://javaconceptoftheday.com/java-8-collectors-tutorial/

https://javaconceptoftheday.com/solving-real-time-queries-using-java-8-features-employee-management-system/

No comments:

Post a Comment

JSP interview questions and answers

Q1. What is JSP and why do we need it? JSP stands for JavaServer Pages. JSP is java server side technology to create dynamic web pages. J...