Based on the conversation, here are the questions the interviewer asked:
Suppose you have a string as a Neelabh. So you need to reverse the string using JDK 8 feature.
Suppose you have a string, say like same string. So you need to find out the count of each character. Like n is coming one time. 8 is coming two time. So you need to find out the count of each character using JDK 8 feature.
Suppose you have an employee table. Employee table has an employee id, employee name and employee salary. You need to find out the second highest salary from the employee table.
What is the diamond problem in Java? And how to overcome?
Can we make the constructor as a final, static, abstract and synchronized?
You have worked with JDK 8 version also. So what are the new features introduced in Java 8?
What is the difference between normal interface and functional interface?
Question : Can functional interface implement another functional interface?
A functional interface can extend another functional interface only if it does not declare any new abstract methods. This is because a functional interface is defined as an interface that has exactly one abstract method. If a functional interface were to declare a new abstract method, it would no longer be a functional interface.
Here’s an example:
@FunctionalInterface
interface InterfaceA {
void methodA();
}
@FunctionalInterface
interface InterfaceB extends InterfaceA {
// No new abstract methods can be declared here
}
In this example, InterfaceB
is a functional interface that extends another functional interface InterfaceA
. It doesn’t declare any new abstract methods, so it’s still a functional interface. The method methodA()
is the single abstract method for both InterfaceA
and InterfaceB
.
If InterfaceB
were to declare a new abstract method, it would no longer be a functional interface, and you would get a compiler error.
@FunctionalInterface
interface InterfaceA {
void methodA();
}
@FunctionalInterface
interface InterfaceB extends InterfaceA {
// It's okay to declare the same method from InterfaceA
void methodA();
}
In this case, InterfaceB
is simply redeclaring the method methodA()
from InterfaceA
. It doesn’t change the fact that InterfaceB
is a functional interface, because there is still only one abstract method across InterfaceA
and InterfaceB
.
However, please note that redeclaring the method in InterfaceB
is not necessary unless you want to provide a different Javadoc comment or annotation for that method in the context of InterfaceB
. The method methodA()
would be inherited from InterfaceA
even if you didn’t redeclare it in InterfaceB
.
What is the difference between comparator and comparable?
In Java, Comparable
and Comparator
are two interfaces used for comparing objects. Here’s how they differ:
Comparable: This interface is used to define the natural order of a class. If a class implements the Comparable
interface, it means that objects of that class can be compared to each other. The Comparable
interface has a single method, compareTo()
, which takes another object of the same type and compares it to the current object. Here’s an example of a class implementing Comparable
:
public class Person implements Comparable<Person> {
private String name;
// constructor, getters and setters...
@Override
public int compareTo(Person other) {
return this.name.compareTo(other.name);
}
}
In this example, Person
objects are compared based on their name
property.
Comparator: This interface is used when you want to define multiple different ways to compare objects, or if you want to compare objects of a class that you do not have control over. The Comparator
interface has a single method, compare()
, which takes two objects and compares them. Here’s an example of a
public class AgeComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return Integer.compare(p1.getAge(), p2.getAge());
}
}
In this example, the AgeComparator
compares Person
objects based on their age
property.
In summary, use Comparable
if you want to define a natural order for objects of a certain class, and use Comparator
if you want to define other ways to compare objects or if you need to compare objects of a class that does not implement Comparable
. Let me know if you have any other questions!
What is the difference between intermediate operation and terminal operation?
In Java’s Stream API, operations are categorized into two groups: intermediate operations and terminal operations. Here’s how they differ:
Intermediate Operations: These operations transform a stream into another stream. They are always lazy, meaning that they do not process the elements of the stream immediately. Instead, they record the operations to be performed and apply them only when a terminal operation is invoked on the stream. Examples of intermediate operations include filter()
, map()
, and sorted()
. Here’s an example of intermediate operations:
List<String> names = Arrays.asList("John", "Jane", "Adam", "Eve"); Stream<String> stream = names.stream().filter(name -> name.startsWith("A")).map(String::toUpperCase);
In this example, filter()
and map()
are intermediate operations. They are not executed until a terminal operation is invoked on stream
.
Terminal Operations: These operations produce a result or a side-effect. Invoking a terminal operation on a stream triggers the processing of the data and consumes the stream. After a terminal operation is invoked, the stream can no longer be used. Examples of terminal operations include forEach()
, reduce()
, collect()
, and sum()
. Here’s an example of a terminal operation: List<String> names = Arrays.asList("John", "Jane", "Adam", "Eve"); long count = names.stream().filter(name -> name.startsWith("A")).count();
In this example, count()
is a terminal operation. It triggers the processing of the filter()
operation and consumes the stream.
In summary, intermediate operations are used to set up a pipeline of operations on a stream, but they don’t actually process any data until a terminal operation is invoked.
What is Return Type of Intermediate Operation and Terminal Operation?
Return Type of Intermediate
Intermediate operations in Java’s Stream API return another Stream. This allows the operations to be connected or chained together. Here are some examples:
map: Transforms the elements of the stream by applying a function to each element. Returns a Stream
consisting of the results of applying the function to the elements of this stream.
Stream<String> stream = Stream.of("a", "b", "c");
Stream<String> upperCaseStream = stream.map(String::toUpperCase);
filter: Filters elements of the stream based on a predicate (a boolean-valued function). Returns a Stream
consisting of the elements of this stream that match the given predicate.
Stream<String> stream = Stream.of("a", "b", "c");
Stream<String> aStream = stream.filter(s -> s.equals("a"));
sorted: Returns a Stream
consisting of the elements of this stream, sorted according to natural order. If the elements of this stream are not Comparable
, a java.lang.ClassCastException
may be thrown when the terminal operation is executed.
Stream<String> stream = Stream.of("c", "a", "b");
Stream<String> sortedStream = stream.sorted();
In each of these examples, the intermediate operation returns a new Stream
that you can further process with other intermediate operations or with a terminal operation. This is what enables the fluent functional programming style that you can use with the Stream API.
Return Type of Terminal
Terminal operations in Java’s Stream API can return different types of results depending on the operation. Here are some examples:
- Collection: The
collect()
operation is used to receive elements from a stream and store them in a collection. For example:List<String> list = stream.collect(Collectors.toList());
In this example,collect()
returns aList<String>
. - Optional: The
findAny()
,findFirst()
,max()
, andmin()
operations return anOptional
that may or may not contain a value. For example:Optional<String> optional = stream.findAny();
In this example,findAny()
returns anOptional<String>
. - Primitive: The
count()
,sum()
,average()
,summaryStatistics()
operations return a primitive value (long
,int
,double
,IntSummaryStatistics
, etc.). For example:long count = stream.count();
In this example,count()
returns along
. - Array: The
toArray()
operation returns an array containing the elements of the stream. For example:Object[] array = stream.toArray();
In this example,toArray()
returns anObject[]
. - Boolean: The
anyMatch()
,allMatch()
, andnoneMatch()
operations return a boolean indicating whether some or all elements of the stream match a given predicate. For example:boolean anyMatch = stream.anyMatch(e -> e.startsWith("A"));
In this example,anyMatch()
returns aboolean
. - Void: The
forEach()
operation returnsvoid
. It’s used for performing an action on each element of the stream. For example:stream.forEach(e -> System.out.println(e));
In this example,forEach()
returnsvoid
.
Remember, once a terminal operation is invoked on a stream, the stream is consumed and can no longer be used.
You have worked with a Spring framework also? Can you give me some annotation which you have used?
What is the difference between controller and REST controller?
What is the use of actuator in Spring Boot?
You have worked with microservices also? How many hours of experience do you have in microservices?
What is the difference between primary key, foreign key and unique key?