Sunday, 12 January 2020

Interview Question java 2020


Java Interview Questions-2020.


Q1. What is Java Serialization?

Primary purpose of java serialization is to write an object into a stream, so that it can be transported through a network and that object can be rebuilt again. When there are two different parties involved, you need a protocol to rebuild the exact same object again. Java serialization API just provides you that. Other ways you can leverage the feature of serialization is, you can use it to perform a deep copy.
Why I used ‘primary purpose’ in the above definition is, sometimes people use java serialization as a replacement for database. Just a placeholder where you can persist an object across sessions. This is not the primary purpose of java serialization. Sometimes, when I interview candidates for Java I hear them saying java serialization is used for storing (to preserve the state) an object and retrieving it. They use it synonymously with database. This is a wrong perception for serialization.

How do you serialize?

When you want to serialize an object, that respective class should implement the marker interface serializable. It just informs the compiler that this java class can be serialized. You can tag properties that should not be serialized as transient. You open a stream and write the object into it. Java API takes care of the serialization protocol and persists the java object in a file in conformance with the protocol. De-serialization is the process of getting the object back from the file to its original form.
Here protocol means, understanding between serializing person and de-serializing person. What will be the contents of file containing the serialized object? This serves as a guideline to de-serialize. Have a look at the following sample and how its serialized file looks.

Sample Source Code for Java Serialization


package com.javapapers.sample;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class SerializationBox implements Serializable {

 private byte serializableProp = 10;

 public byte getSerializableProp() {
  return serializableProp;
 }
}

public class SerializationSample {

 public static void main(String args[]) throws IOException,
   FileNotFoundException, ClassNotFoundException {

  SerializationBox serialB = new SerializationBox();
  serialize("serial.out", serialB);
  SerializationBox sb = (SerializationBox) deSerialize("serial.out");
  System.out.println(sb.getSerializableProp());
 }

 public static void serialize(String outFile, Object serializableObject)
   throws IOException {
  FileOutputStream fos = new FileOutputStream(outFile);
  ObjectOutputStream oos = new ObjectOutputStream(fos);
  oos.writeObject(serializableObject);
 }

 public static Object deSerialize(String serilizedObject)
   throws FileNotFoundException, IOException, ClassNotFoundException {
  FileInputStream fis = new FileInputStream(serilizedObject);
  ObjectInputStream ois = new ObjectInputStream(fis);
  return ois.readObject();
 }
}

Exploring Java Serialization

Look at following image. After serializing ‘SerializationBox’ in the above sample code, I opened the output in a hex editor. You can use Notepad++ and hex plugin to open the serialized file.
Let us look at contents byte by byte and find out what they are. It starts with “ac ed”. It is is called STREAM_MAGIC. It is a magic number (java API guys says) that is written to the stream header. It denotes that is start of serialzed content.Serialized Output
Similarly every character has a meaning. Actually the serialized file is more bulkier than you would expect, as it has a huge header the meta information of the classes involved and finally the content. Object Serialization Stream Protocol have a look at chapter 6.4.2 Terminal Symbols and Constants. It gives you list of symbols and constants used in serialization.

Decrypting Serialized Java Object

In the image, I have underline a unit of information in a separate color for you to easily identify.
ac ed – STREAM_MAGIC – denotes start of serialzed content
00 05 – STREAM_VERSION – serialization version
73 – TC_OBJECT – new Object
72 – TC_CLASSDESC – new Class Descriptor
00 26 – length of the class name
63 6f 6d 2e 6a 61 76 61 70 61 70 65 72 73 2e 73 61 6d 70 6c 65 2e 53 65 72 69 61 6c 69 7a 61 74 69 6f 6e 42 6f 78 – class name
57 fc 83 ca 02 85 f0 18 – SerialVersionUID
02 – this object is serializable
00 01 – count of properties in the serialzed class – one property in our example
42 00 10 – private byte
73 65 72 69 61 6c 69 7a 61 62 6c 65 50 72 6f 70 78 70 – property name – serializableProp in our example
0a – 10 the value – This is the persisted value of the property in our sample


Q2. What is the use of seriaversionUID while implementing the Serializable interface?
        private static final long serialVersionUID = 1L;

Ans:

How serialVersionUID is generated?

serialVersionUID is a 64-bit hash of the class name, interface class names, methods and fields. Serialization runtime generates a serialVersionUID if you do not add one in source. Refer this link for the algorithm to generate serialVersionUID.
It is advised to have serialVersionUID as unique as possible. Thats why the java runtime chose to have such a complex algorithm to generate it.
If you want help in generating it, jdk tools provides a tool named serialver. Use serialver -show to start the gui version of the tool as shown below.


How serialVersionUID works?

When an object is serialized, the serialVersionUID is serialized along with the other contents.
Later when that is deserialized, the serialVersionUID from the deserialized object is extracted and compared with the serialVersionUID of the loaded class.
If the numbers do not match then, InvalidClassException is thrown.
If the loaded class is not having a serialVersionUID declared, then it is automatically generated using the same algorithm as before.

Strongly recommended to declare serialVersionUID

Javadocs says,

“the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassExceptions during deserialization”
Now you know why we should declare a serialVersionUID.
Not only declaring a serialVersionUID is sufficient. You must do the following two things carefully. Otherwise it defeats the purpose of having the serialVersionUID.
serialVersionUID should be maintained. As and when you change anything in the class, you should upgrade the serailVersionUID.
Try your best to declare a unique serialVersionUID.


Demonstrate serialVersionUID

Initial class to be serialized has a serialVersionUID as 1L.

import java.io.Serializable;

public class Lion implements Serializable {

  private static final long serialVersionUID = 1L;
  private String sound;

  public Lion(String sound) {
    this.sound = sound;
  }

  public String getSound() {
    return sound;
  }

}
Test serialVersionUID:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerialVersionUIDTest {

  public static void main(String args[]) throws IOException, ClassNotFoundException {
    Lion leo = new Lion("roar");
    // serialize

    System.out.println("Serialization done.");
    FileOutputStream fos = new FileOutputStream("serial.out");
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(leo);

    // deserialize
    FileInputStream fis = new FileInputStream("serial.out");
    ObjectInputStream ois = new ObjectInputStream(fis);
    Lion deserializedObj = (Lion) ois.readObject();
    System.out.println("DeSerialization done. Lion: " + deserializedObj.getSound());
  }
}

Output:


Serialization done.
DeSerialization done. Lion: roar
Now change serialVersionUID to 2L in Lion class.

  private static final long serialVersionUID = 2L;
Comment the “serialize” block (4 lines of code) in SerialVersionUIDTest. Now run it and you will get the following exception.

  1. Serialized Lion with serialVersionUID with 1L.
  2. Changed serialVersionUID to 2L and compiled and loaded the class.
  3. Deserialize the already serialized object and load it with the latest class.
  4. We get exception as serialVersionUID is not matching.

Exception in thread "main" java.io.InvalidClassException: Lion;
 local class incompatible: stream classdesc serialVersionUID = 1, 
local class serialVersionUID = 2
 at java.io.ObjectStreamClass.initNonProxy(Unknown Source)
 at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
 at java.io.ObjectInputStream.readClassDesc(Unknown Source)
 at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
 at java.io.ObjectInputStream.readObject0(Unknown Source)
 at java.io.ObjectInputStream.readObject(Unknown Source)
 at SerialVersionUIDTest.main(SerialVersionUIDTest.java:21)
Points to remember
1. If a parent class has implemented Serializable interface then child class doesn’t need to implement it but vice-versa is not true.
2. Only non-static data members are saved via Serialization process.
3. Static data members and transient data members are not saved via Serialization process.So, if you don’t want to save value of a non-static data member then make it transient.
4. Constructor of object is never called when an object is deserialized.
5. Associated objects must be implementing Serializable interface.

In case of transient variables:- A variable defined with transient keyword is not serialized during serialization process.This variable will be initialized with default value during deserialization. (e.g: for objects it is null, for int it is 0).
In case of static Variables:- A variable defined with static keyword is not serialized during serialization process.This variable will be loaded with current value defined in the class during deserialization.

Q3. Difference between shallow copy and deep copy.
Ans: 

Shallow Copy Vs Deep Copy In Java :

Below is the list of differences between shallow copy and deep copy in java.

Shallow Copy Deep Copy
Cloned Object and original object are not 100% disjoint. Cloned Object and original object are 100% disjoint.
Any changes made to cloned object will be reflected in original object or vice versa. Any changes made to cloned object will not be reflected in original object or vice versa.
Default version of clone method creates the shallow copy of an object. To create the deep copy of an object, you have to override clone method.
Shallow copy is preferred if an object has only primitive fields. Deep copy is preferred if an object has references to other objects as fields.
Shallow copy is fast and also less expensive. Deep copy is slow and very expensive.


Q4. What are the ways of creating an instance of a singleton class?

What is the purpose of Singleton?



The purpose of the Singleton class is to control object creation, limiting the number of objects to only one. The singleton allows only one entry point to create the new instance of the class.
Since there is only one Singleton instance, any instance fields of a Singleton will occur only once per class, just like static fields. Singletons are often useful where you have to control the resources, such as database connections or sockets.
It seems to be a simple design pattern but when it comes to implementation, it comes with a lot of implementation concerns. The implementation of Singleton pattern has always been a controversial topic among developers. Here, you are going to discuss how to create a Singleton class that fulfills its purpose :
Restrict the instantiation of a class and ensures that only one instance of the class exists in the java virtual machine.
Let’s create Singleton class in java and test it in different conditions.


Create Singleton class



To implement the Singleton class, the simplest way is to make the constructor of the class as private. There are two approaches for the initialization.

1. Eager initialization:

In eager initialization, the instance of Singleton Class is created at the time of class loading, this is the easiest method to create a Singleton class.
By making the constructor as private you are not allowing other class to create a new instance of the class you want to create the Singleton. Instead, you are creating one public static method (commonly name as for getInstance()) to provide the single entry point to create the new instance of the class.

public class SingletonClass {

private static volatile SingletonClass sSoleInstance = new SingletonClass();

//private constructor.
private SingletonClass(){}

public static SingletonClass getInstance() {
return sSoleInstance;
}
}

This approach has one drawback. Here instance is created even though client application might not be using it. This might be a considerable issue if your
Singleton class in creating a database connection or creating a socket. This may cause the memory leak problem. The solution is to create the new instance of the class, when needed. This can be achieved by Lazy Initialization method.

2. Lazy initialization:

Opposite to Eager initialization, here you are going to initialize new instance of the class in getInstance() method it self. This method will check if there is any instance of that class is already created? If yes, then our method (getInstance()) will return that old instance and if not then it creates a new instance of the singleton class in JVM and returns that instance. This approach is called as Lazy initialization.

public class SingletonClass {

    private static SingletonClass sSoleInstance;

    private SingletonClass(){}  //private constructor.

    public static SingletonClass getInstance(){
        if (sSoleInstance == null){ //if there is no instance available... create new one
            sSoleInstance = new SingletonClass();
        }

        return sSoleInstance;
    }
}

We all know that in Java if the two objects are same then, their hash key have to be equal. Let’s test that. If the above Singleton is correctly implemented than below code should return the same hash key.

public class SingletonTester {
   public static void main(String[] args) {
        //Instance 1
        SingletonClass instance1 = SingletonClass.getInstance();

        //Instance 2
        SingletonClass instance2 = SingletonClass.getInstance();

        //now lets check the hash key.
        System.out.println("Instance 1 hash:" + instance1.hashCode());
        System.out.println("Instance 2 hash:" + instance2.hashCode());  
   }
}

Below is the output log with the hash code of both the instances.




Both have the same hash.

You can see that both the instances are having the same hash code. So, that means above code will make the perfect Singleton. Right???? No.


Make Singleton reflection proof



In above Singleton class, by using reflection you can create more than one instance. If you don’t know what is the Java Reflection API is, Java Reflection is a process of examining or modifying the run-time behavior of a class at run time.
You can make the new instance of the Singleton class by changing the constructor visibility as public in run-time and create new instance using that constructor. Run the below code and see it our Singleton class survives?

public class SingletonTester {
   public static void main(String[] args) {
        //Create the 1st instance
        SingletonClass instance1 = SingletonClass.getInstance();
        
        //Create 2nd instance using Java Reflection API.
        SingletonClass instance2 = null;
        try {
            Class<SingletonClass> clazz = SingletonClass.class;
            Constructor<SingletonClass> cons = clazz.getDeclaredConstructor();
            cons.setAccessible(true);
            instance2 = cons.newInstance();
        } catch (NoSuchMethodException | InvocationTargetException 
             | IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }

        //now lets check the hash key.
        System.out.println("Instance 1 hash:" + instance1.hashCode());
        System.out.println("Instance 2 hash:" + instance2.hashCode());
   }
}

Here is the output of hash codes of both instances.



Testing reflection

Both the instances have a different hash code. That clearly indicates that Singleton class failed this test.

Solution:

To prevent Singleton failure while due to reflection you have to throw a run-time exception in constructor, if the constructor is already initialized and some class to initialize it again. Let’s update SingletonClass.java.
public class SingletonClass {

    private static SingletonClass sSoleInstance;

    //private constructor.
    private SingletonClass(){
       
        //Prevent form the reflection api.
        if (sSoleInstance != null){
            throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
        }
    } 

    public static SingletonClass getInstance(){
        if (sSoleInstance == null){ //if there is no instance available... create new one
            sSoleInstance = new SingletonClass();
        }

        return sSoleInstance;
    }
}






Make Singleton thread safe



If two threads try to initialize the Singleton class at almost the same time, what happens? Let’s test below code in which two threads are created almost simultaneously and they are calling getInstance().
public class SingletonTester {
   public static void main(String[] args) {
        //Thread 1
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                SingletonClass instance1 = SingletonClass.getInstance();
                System.out.println("Instance 1 hash:" + instance1.hashCode());
            }
        });

        //Thread 2
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                SingletonClass instance2 = SingletonClass.getInstance();
                System.out.println("Instance 2 hash:" + instance2.hashCode());
            }
        });

        //start both the threads
        t1.start();
        t2.start();
   }
}

If you run this code many times, you will see sometimes both the threads creates different instances.




That means your Singleton class is not Thread safe. Both the threads calls out getInstance() method at the same time, the sSoleInstance == null condition will return for both the thread. So, two different instances of the same class will be created. That will break the singleton principle.

Solution:

1. Make getInstance() synchronized:

Let’s make getInstance() method synchronized.
public class SingletonClass {

    private static SingletonClass sSoleInstance;

    //private constructor.
    private SingletonClass(){
       
        //Prevent form the reflection api.
        if (sSoleInstance != null){
            throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
        }
    } 

    public synchronized static SingletonClass getInstance(){
        if (sSoleInstance == null){ //if there is no instance available... create new one
            sSoleInstance = new SingletonClass();
        }

        return sSoleInstance;
    }
}
As you made your getInstance() class synchronized the second thread will have to wait until the getInstance() method is completed for the first thread. This way we can achieve thread safety.
But, there are some cons of using this approach:
  • Slow performance because of locking overhead.
  • Unnecessary synchronization that is not required once the instance variable is initialized.

2. Double check locking method:

You can overcome this issue if you use Double check locking method to create the Singleton.
In this, you will make the Singleton class in the synchronized block if the instance is null. So, the synchronized block will be executed only when the sSoleInstance is null and prevent unnecessary synchronization once the instance variable is initialized.

public class SingletonClass {

    private static SingletonClass sSoleInstance;

    //private constructor.
    private SingletonClass(){

        //Prevent form the reflection api.
        if (sSoleInstance != null){
            throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
        }
    }

    public static SingletonClass getInstance() {
        //Double check locking pattern
        if (sSoleInstance == null) { //Check for the first time
          
            synchronized (SingletonClass.class) {   //Check for the second time.
              //if there is no instance available... create new one
              if (sSoleInstance == null) sSoleInstance = new SingletonClass();
            }
        }

        return sSoleInstance;
    }
}

3. Use volatile keyword:

On the surface, this method looks perfect, as you only need to pay price for synchronized block one time, but it still was broken, until you make sSoleInstance variable volatile.
Without volatile modifier, it’s possible for another thread in Java to see half initialized state of sSoleInstance variable, but with volatile variable guaranteeing happens-before relationship, all the write will happen on volatile sSoleInstance before any read of sSoleInstance variable.

public class SingletonClass {

    private static volatile SingletonClass sSoleInstance;

    //private constructor.
    private SingletonClass(){

        //Prevent form the reflection api.
        if (sSoleInstance != null){
            throw new RuntimeException("Use getInstance() 
method to get the single instance of this class.");
        }
    }

    public static SingletonClass getInstance() {
        //Double check locking pattern
        if (sSoleInstance == null) { //Check for the first time
          
            synchronized (SingletonClass.class) {   //Check for the second time.
              //if there is no instance available... create new one
              if (sSoleInstance == null) sSoleInstance = new SingletonClass();
            }
        }

        return sSoleInstance;
    }
}

Now, above Singleton class is thread safe. Making Singleton thread safe is especially required in multi-threaded application environment like in Android Applications.


Make Singleton safe from Serialization



Sometimes in distributed systems, you need to implement Serializable interface in Singleton class. By doing that you can store its state in the file system and retrieve it at later point of time.
Let’s test singleton class whether it maintains single instance after serializable and deserializable operations?




public class SingletonTester {
   public static void main(String[] args) {
      
      try {
            SingletonClass instance1 = SingletonClass.getInstance();
            ObjectOutput out = null;

            out = new ObjectOutputStream(new FileOutputStream("filename.ser"));
            out.writeObject(instance1);
            out.close();

            //deserialize from file to object
            ObjectInput in = new ObjectInputStream(new FileInputStream("filename.ser"));
            SingletonClass instance2 = (SingletonClass) in.readObject();
            in.close();

            System.out.println("instance1 hashCode=" + instance1.hashCode());
            System.out.println("instance2 hashCode=" + instance2.hashCode());

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
   }
}


You can see that the hash code of both the instances are different. That is clearly violates singleton principle. The problem with above serialized singleton class is that whenever we deserialize it, it will create a new instance of the class.
To prevent creation of another instance you have to provide the implementation of readResolve() method. readResolve() replaces the object read from the stream. This ensures that nobody can create another instance by serializing and deserializing the singleton.
public class SingletonClass implements Serializable {

    private static volatile SingletonClass sSoleInstance;

    //private constructor.
    private SingletonClass(){

        //Prevent form the reflection api.
        if (sSoleInstance != null){
            throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
        }
    }

    public static SingletonClass getInstance() {
        if (sSoleInstance == null) { //if there is no instance available... create new one
            synchronized (SingletonClass.class) {
                if (sSoleInstance == null) sSoleInstance = new SingletonClass();
            }
        }

        return sSoleInstance;
    }

    //Make singleton from serialize and deserialize operation.
    protected SingletonClass readResolve() {
        return getInstance();
    }
}

At end of the article, you can make your class a Singleton class that is thread, reflection and serialization safe. This Singleton is still not the perfect Singleton. You can violate the Singleton principle by creating more than one instance of the Singleton class by using cloning or using multiple class loaders. But for the most of the applications, above implementation of Singleton will work perfectly.

Q4. What is the difference between map and flat map in java stream API?
Ans:

In Java, Stream interface has >map() and flatMap() methods and both are intermediate stream operations and return another stream as method output. The primary difference between map() vs flatMap() is the return type of both methods.
map() is used for transformation only, but flatMap() is used for both transformation and flattening.
flatMap() = map() + Flattening

1. Difference between map() and flatMap()

The map() method produces one output value for each input value in the stream. So if there are n elements in the stream, map() operation will produce a stream of n output elements.
map() example
List<String> listOfStrings = Arrays.asList("1", "2", "3", "4", "5");
List<Integer> listOfIntegers = listOfStrings.stream()
                                .map(Integer::valueOf)
                                .collect(Collectors.toList());
System.out.println(listOfIntegers);     //[1, 2, 3, 4, 5]
flatMap() is two step process i.e. map() + Flattening. It helps in converting Collection<Collection<T>> to Collection<T>.
flatMap() example
List<Integer> list1 = Arrays.asList(1,2,3);
List<Integer> list2 = Arrays.asList(4,5,6);
List<Integer> list3 = Arrays.asList(7,8,9);
List<List<Integer>> listOfLists = Arrays.asList(list1, list2, list3);
List<Integer> listOfAllIntegers = listOfLists.stream()
                            .flatMap(x -> x.stream())
                            .collect(Collectors.toList());
System.out.println(listOfAllIntegers);      //[1, 2, 3, 4, 5, 6, 7, 8, 9]

2. Usage of map() vs flatMap()

We can use map() operation when we have a stream of objects, and we need to get some unique value for each element in the stream. There is one-to-one mapping between input and output element. For example, we can write a program to find the date of birth of all employees in a stream of employees.
In case of flatMap(), a one-to-many mapping is created where for each input element/stream, we first get a multiple values and then we flatten the values from all such input streams into a single output stream. For example, we may write program to find all district words from all lines in a text file.


Q5. What are the built-in interfaces included in the java.util.function package such as Predicate, Consumer, Function, and Supplier?

Functional interfaces provide target types for lambda expressions and method references. Each functional interface has a single abstract method, called functional method for that functional interface, to which the lambda expression's parameter and return types are matched or adapted.

Predicate

A predicate is a statement that may be true or false depending on the values of its variables. It can be thought of as a function that returns a value that is either true or false.
In Java 8, a Predicate is a functional interface that can be used anywhere you need to evaluate a boolean condition. Since it's a functional interface, you can pass a lambda expression wherever a Predicate is expected.
See the API to know the methods of this interface.
Here's an example. First, we see how the interface with an anonymous class:
Predicate<String> isALongWord = new Predicate<String>() {
    @Override
    public boolean test(String t) {
        return t.length() > 10;
    }
};
String s = "successfully"
boolean result = isALongWord.test(s);
 
And now with a lambda expression:

Predicate<String> isALongWord = t -> t.length() > 10;
String s = "successfully"
boolean result = isALongWord.test(s);
 
Predicates are also used to filter collections, for example:
public class Test {
  public static void main(String[] args) {
    List<String> l = new ArrayList<>();
    l.add("successfully");
    l.add("easy");
    l.add("fortune");
    List<String> filtered = l.stream().filter( s -> s.length() > 5 ).collect(Collectors.<String>toList());
    System.out.println(filtered);
  }
}
 
Here, the filter method expects a Predicate, so we can pass a lambda expression to simplify things, so the output of the example is:
["successfully", "fortune"]

Consumer

This functional interface represents an operation that accepts a single input argument and returns no result. The real outcome is the side-effects it produces. Since it's a functional interface, you can pass a lambda expression wherever a Consumer is expected.
See the API to know the methods of this interface.
Here's an example:
class Product {
  private double price = 0.0;

  public void setPrice(double price) {
    this.price = price;
  }

  public void printPrice() {
    System.out.println(price);
  }
}

public class Test {
  public static void main(String[] args) {
    Consumer<Product> updatePrice = p -> p.setPrice(5.9);
    Product p = new Product();
    updatePrice.accept(p);
    p.printPrice();
  }
}
 
Basically, what Consumer does is executing the assigned lambda expression. The side-effect here, it's the updating of the product's price, so the output is:
5.9

Function

This functional interface represents a function that accepts one argument and produces a result. One use, for example, it's to convert or transform from one object to another. Since it's a functional interface, you can pass a lambda expression wherever a Function is expected.
See the API to know the methods of this interface.
Here's an example:

public class Test {
  public static void main(String[] args) {
    int n = 5;
    modifyTheValue(n, val-> val + 10);
    modifyTheValue(n, val-> val * 100);
  }

  static void modifyValue(int v, Function<Integer, Integer> function){
    int result = function.apply(v);
    System.out.println(newValue);
  }

}
The input parameter type and the return type of the method can either be same or different. In this case, they are the same type and the program just execute the functions represented by the lambda expression, an addition and a multiplication, so the output is:
15
500

Supplier

This functional interface does the opposite of the Consumer, it takes no arguments but it returns some value. It may return different values when it is being called more than once. Since it's a functional interface, you can pass a lambda expression wherever a Supplier is expected.
See the API to know the one method of this interface.
Here's an example:
public class Program {
    public static void main(String[] args) {
        int n = 3;
        display(() -> n + 10);
        display(() -> n + 100);
    }

    static void display(Supplier<Integer> arg) {
        System.out.println(arg.get());
    }
}
Basically, a Supplier just provides values. The output of the example is:
13
103

Develop code that uses primitive versions of functional interfaces

Due to the way generics are implemented, parameters of the functional interfaces (for example, Predicate<T>) can be bound only to reference types (like String, objects, etc).
If you want to use primitive types with these functional interfaces, Java uses a mechanism called autoboxing to automatically convert a primitive to its corresponding wrapper type (for example, int to Integer) and vice versa.
But since boxed values use more memory, this comes with a performance cost. For this reason, Java provides specialized versions of the functional interfaces to avoid autoboxing operations when the inputs or outputs are primitives.
For example, instead of using
Predicate<Integer> p = i -> i > 10;
You can use
IntPredicate p = i -> i > 10;
In general, the names of functional interfaces that have a primitive version for the input parameter are preceded by the primitive type, like IntPredicate. The Function interface also has variants for the output parameter like ToIntFunction<T>.
Here's a summary of the primitive version of functional interfaces with a link to their javadoc:
Predicate<T>
IntPredicate. Predicate of one int-valued argument.
LongPredicate. Predicate of one long-valued argument.
DoublePredicate. Predicate of one double-valued argument.
Consumer<T>
IntConsumer. Operation that accepts a single int-valued argument and returns no result.
LongConsumer. Operation that accepts a single long-valued argument and returns no result.
DoubleConsumer. Operation that accepts a single double-valued argument and returns no result.
Function<T, R>
IntFunction<R>. Function that accepts an int-valued argument and produces a result.
IntToDoubleFunction. Function that accepts an int-valued argument and produces a double-valued result.
IntToLongFunction. Function that accepts an int-valued argument and produces a long-valued result.
LongFunction<R>. Function that accepts a long-valued argument and produces a result.
LongToDoubleFunction. Function that accepts a long-valued argument and produces a double-valued result.
LongToIntFunction. Function that accepts a long-valued argument and produces an int-valued result.
DoubleFunction<R>. Function that accepts a double-valued argument and produces a result.
ToIntFunction<T>. Function that produces an int-valued result.
ToDoubleFunction<T>. Function that produces a double-valued result.
ToLongFunction<T>. Function that produces a long-valued result.
Supplier<T>
BooleanSupplier. Supplier of boolean-valued results.
IntSupplier. Supplier of int-valued results.
LongSupplier. Supplier of long-valued results.
DoubleSupplier. Supplier of double-valued results.
UnaryOperator<T>
IntUnaryOperator. Function operation on a single int-valued operand that produces an int-valued result.
LongUnaryOperator. Function operation on a single long-valued operand that produces a long-valued result.
DoubleUnaryOperator. Function operation on a single double-valued operand that produces a double-valued result.

Develop code that uses binary versions of functional interfaces

The following functional interfaces:
  • Predicate<T>
  • Consumer<T>
  • Function<T,R>
  • UnaryOperator<T>
Represent an operation that takes one argument. But there are versions of these interfaces that take two arguments called. These are the binary versions. They have the same semantics, the only difference is the number of arguments. Note there is no binary version of Supplier. This is because a Supplier takes no arguments.
Here's a summary of the binary versions of the functional interfaces along with their primitive versions and a link to their javadoc:
BiPredicate<L, R>
(No primitive versions)
BiConsumer<T, U>
ObjIntConsumer<T>. Operation that accepts an Object-valued and an int-valued argument and returns no result.
ObjLongConsumer<T>. Operation that accepts an Object-valued and a long-valued argument and returns no result.
ObjDoubleConsumer<T>. Operation that accepts an Object-valued and a double-valued argument and returns no result.
BiFunction<T, U, R>
ToIntBiFunction<T, U>. Function that accepts two arguments and produces an int-valued result.
ToLongBiFunction<T, U>. Function that accepts two arguments and produces a long-valued result.
ToDoubleBiFunction<T, U>. Function that accepts two arguments and produces a double-valued result.
BinaryOperator<T>
IntBinaryOperator. Function operation upon two int-valued operands and producing an int-valued result.
LongBinaryOperator. Function operation upon two long-valued operands and producing a long-valued result.
DoubleBinaryOperator. Function operation upon two double-valued operands and producing a double-valued result.

Develop code that uses the UnaryOperator interface

UnaryOperator is a functional interface that receives a value of a certain type and returns a value of the same type. This is a specialization of the Function interface for the case where the operand and result are of the same type (in fact UnaryOperator extends from Function).
Here's the javadoc.
And here's an example:
public class Test {
  public static void main(String[] args) {

      UnaryOperator<Integer> unary = v -> v * 10;
      // This means the same as the UnaryOperator above.
      Function<Integer, Integer> function = v -> v * 10;

      System.out.println(unary.apply(10));
      System.out.println(function.apply(10));
  }
}
The output:
100
100
The UnaryOperator can also be applied to a collection like this:
public class Program {
  public static void main(String[] args) {
      List<Integer> list = new ArrayList<>();
      list.add(1);
      list.add(2);
      list.add(3);
      list.replaceAll(i -> i * 10);
      // ... Display the results.
      System.out.println(list);
  }
}
The output:
[10, 20, 30]

Note:

BiConsumer, BiFunction and BiPredicate Interface.

BiConsumer, BiFunction and BiPredicate Interface All these Interfaces are similar to above mentioned interface the only difference is these interface accept two input parameters and returns a result.


Q5. Given the structure of class Student and Subject. You have a list of students with their corresponding subject and marks return top marks of each subject from studentList.class 

Student{
        private String name;    
        private UUId id;    
        List<Subject> subjectList;
} 
class Subject{   
      private String subjectName;   
      private Double Marks;
}

Solution:

1. First below code will flatten subject object in one list.
List<Subject> sl = studentList.stream().flatMap(s->s.getSubjectList().stream().distinct()).collect(Collectors.toList());

2. Second below code will group the resultant list by subject name and after grouping it will return max Marks on that subject using natural ordering.

Map<String, Optional<Integer>> sl1 = studentList.stream().flatMap(s->s.getSubjectList().stream().distinct()).collect(Collectors.groupingBy(Subject::getSubjectName, Collectors.mapping(Subject::getMarks, Collectors.maxBy(Comparator.naturalOrder()))));

Q6. What is functional interface and how to create functional interface ?

Solution: 
An interface with exactly one abstract method is called Functional Interface. @FunctionalInterface annotation is added so that we can mark an interface as functional interface.

It is not mandatory to use it, but it’s best practice to use it with functional interfaces to avoid addition of extra methods accidentally. If the interface is annotated with @FunctionalInterface annotation and we try to have more than one abstract method, it throws compiler error.
The major benefit of java 8 functional interfaces is that we can use lambda expressions to instantiate them and avoid using bulky anonymous class implementation.
Here is a Java functional interface example:
public interface MyFunctionalInterface {
    public void execute();
}
The above counts as a functional interface in Java because it only contains a single method, and that method has no implementation. Normally a Java interface does not contain implementations of the methods it declares, but it can contain implementations in default methods, or in static methods. Below is another example of a Java functional interface, with implementations of some of the methods:
public interface MyFunctionalInterface2{
    public void execute();

    public default void print(String text) {
        System.out.println(text);
    }

    public static void print(String text, PrintWriter writer) throws IOException {
        writer.write(text);
    }
}
The above interface still counts as a functional interface in Java, since it only contains a single non-implemented method.

Functional Interfaces Can Be Implemented by a Lambda Expression

A Java functional interface can be implemented by a Java Lambda Expression. Here is an example that implements the functional interface MyFunctionalInterface defined in the beginning of this Java functional interface tutorial:
MyFunctionalInterface lambda = () -> {
    System.out.println("Executing...");
}
A Java lambda expression implements a single method from a Java interface. In order to know what method the lambda expression implements, the interface can only contain a single unimplemented method. In other words, the interface must be a Java functional interface.

Q1. How to make class thread-safe?
Solution: Read article for description.
https://dzone.com/articles/5-tips-to-make-your-classes-thread-safe
1) Declare Immutable Member Variables as Final.

2) Create Objects Eagerly

3) Use Volatile for Mutable Boolean Variables

4) Check 3rd Party Classes are thread safe or not if 3rd party classes are used which are not thread save then it will fail our motive.



Q2. What is completableFuture?

https://www.callicoder.com/java-8-completablefuture-tutorial/

CompletableFuture is used for asynchronous programming in Java. Asynchronous programming is a means of writing non-blocking code by running a task on a separate thread than the main application thread and notifying the main thread about its progress, completion or failure.
This way, your main thread does not block/wait for the completion of the task and it can execute other tasks in parallel.
Having this kind of parallelism greatly improves the performance of your programs.

Future vs CompletableFuture

CompletableFuture is an extension to Java’s Future API which was introduced in Java 5.
A Future is used as a reference to the result of an asynchronous computation. It provides an isDone() method to check whether the computation is done or not, and a get() method to retrieve the result of the computation when it is done.
You can learn more about Future from Callable and Future Tutorial.
Future API was a good step towards asynchronous programming in Java but it lacked some important and useful features -

Limitations of Future

  1. It cannot be manually completed :
    Let’s say that you’ve written a function to fetch the latest price of an e-commerce product from a remote API. Since this API call is time-consuming, you’re running it in a separate thread and returning a Future from your function.
    Now, let’s say that If the remote API service is down, then you want to complete the Future manually by the last cached price of the product.
    Can you do this with Future? No!
  2. You cannot perform further action on a Future’s result without blocking:
    Future does not notify you of its completion. It provides a get() method which blocks until the result is available.
    You don’t have the ability to attach a callback function to the Future and have it get called automatically when the Future’s result is available.
  3. Multiple Futures cannot be chained together :
    Sometimes you need to execute a long-running computation and when the computation is done, you need to send its result to another long-running computation, and so on.
    You can not create such asynchronous workflow with Futures.
  4. You can not combine multiple Futures together :
    Let’s say that you have 10 different Futures that you want to run in parallel and then run some function after all of them completes. You can’t do this as well with Future.
  5. No Exception Handling :
    Future API does not have any exception handling construct.
Whoa! So many limitations right? Well, That’s why we have CompletableFuture. You can achieve all of the above with CompletableFuture.
 CompletableFuture implements Future and CompletionStage interfaces and provides a huge set of convenience methods for creating, chaining and combining multiple Futures. It also has a very comprehensive exception handling support.


 

Q3. What are the implementations class of ExecutorService?
Q4. What is the difference between dequeBlocking and queueBlocking?
Q5. Difference between completable future and future?
Q6. What is the difference between sleep(), wait() and yield()?