Core Java Interview Booster 8
Core Java Interview Booster 8
=====================================================================
Yes, in Java, you can create a generic class to handle different data types without
specifying the exact type at the time of class definition. Generics provide a way
to create classes, interfaces, and methods with type parameters, allowing for code
reusability and type safety.
```java
// A generic class with one type parameter
class Box<T> {
private T value;
public T get() {
return value;
}
}
You can also have multiple type parameters if needed, like `Box<T, U>`. Would you
like more details on how to extend this concept?
========================
In Java, you can declare a **generic method** to work with different types of
parameters. Just like a generic class, a generic method provides type safety and
reusability, allowing the method to operate on various data types.
### Explanation:
- The method `printArray` is a **generic method** with a type parameter `T`.
- `<T>` before the return type `void` declares that this method is generic and can
handle any type of array.
- The method can be called with different types of arrays (like `Integer[]`,
`String[]`, etc.), and it will print the elements of the array.
You can also declare a generic method with multiple type parameters.
```java
public class MultipleGenericsExample {
### Explanation:
- `<T, U>` declares two type parameters.
- The method `printKeyValue` can handle pairs of different types (e.g., `Integer`
and `String`, `String` and `Double`).
Would you like to explore more specific examples or advanced usage of generics?
========================
In method overloading in Java, the return type is **not considered** as part of the
method signature. Therefore, method overloading is determined based on the **method
name** and the **parameter list** (number, types, and order of parameters). The
return type **alone** cannot distinguish overloaded methods.
### Example:
```java
public class OverloadExample {
// This would cause a compile-time error because only the return type is
different
// public String display(String str) {
// return str; // Error: method already defined with the same parameter
list
// }
### Explanation:
- The methods `display(String str)` and `display(int num)` are valid overloads
because their parameter lists are different.
- However, you cannot overload a method **solely** based on its return type. If you
tried to add a method like `public String display(String str)`, it would result in
a **compile-time error**, as the parameter list is the same as the other
`display(String str)` method.
### Summary:
- **Overloading**: Return type is **not considered**; only method name and
parameters matter.
- **Overriding**: Covariant return types are allowed, where the return type of the
overriding method can be a subclass of the return type in the superclass.
### Example:
```java
import java.util.List;
If you need to add elements to the list, you can convert the immutable list to a
**mutable list** like `ArrayList` or `LinkedList`. You can do this by passing the
immutable list to the constructor of a mutable list.
```java
import java.util.List;
import java.util.ArrayList;
### Steps:
1. Create an immutable list using `List.of()`.
2. Convert it to a mutable list (e.g., `ArrayList`).
3. Add elements to the mutable list using the `add()` method.
If you'd like more information on working with lists in Java, feel free to ask!
==================
Yes, you can create objects of a class inside a `for` loop and access methods from
that class. Each iteration of the loop will create a new instance (object) of the
class, and you can call its methods.
### Example:
```java
class Person {
String name;
// Constructor
Person(String name) {
this.name = name;
}
### Output:
```
Person's Name: Alice
Person's Name: Bob
Person's Name: Charlie
```
### Explanation:
- In each iteration of the loop, a new `Person` object is created with a different
name.
- The `display()` method is called on each `Person` object to print the name.
Let's focus on **local blocks inside a method**, since that is likely what you're
asking about.
### Example:
```java
public class Main {
public void exampleMethod() {
System.out.println("Start of Method");
System.out.println("End of Method");
}
2. **Memory Management**: Limiting the scope of variables ensures that once the
local block is finished, the memory allocated for variables is freed. This is
especially helpful in methods with long execution paths or loops where memory usage
needs to be optimized.
```java
public class Main {
public void calculate() {
int result;
Here, the variables `a` and `b` are limited to the local block, but the `result`
can be used outside because it was declared outside the block.
### Conclusion:
- A **local block** in a method helps group code and limit the scope of variables
for better readability, memory optimization, and reducing errors.
- It's useful for temporarily isolating logic and improving code structure.
Would you like more details on any specific type of code block?
========================
In Java, the `Arrays.compare()` method was introduced in **Java 9** as part of the
`java.util.Arrays` class. It allows you to compare two arrays lexicographically,
element by element. This method is typically used for comparing arrays of primitive
types (e.g., `int[]`, `double[]`) or arrays of objects that implement the
`Comparable` interface (e.g., `String[]`).
### Syntax:
```java
Arrays.compare(array1, array2);
```
- If the first array is lexicographically smaller than the second array, the method
returns a negative integer.
- If the first array is lexicographically larger, the method returns a positive
integer.
- If the two arrays are equal (all corresponding elements are the same), it returns
`0`.
```java
import java.util.Arrays;
### Explanation:
- The method compares the two arrays element by element in lexicographical order.
- In this case, since `"cherry"` is lexicographically smaller than `"date"`, `arr1`
is considered smaller than `arr2`, so the output will be:
```
arr1 is lexicographically smaller than arr2.
```
### Explanation:
- Here, the first two elements of both arrays are equal (`1` and `2`).
- The third element of `arr1` (`3`) is smaller than the third element of `arr2`
(`4`), so the result will be:
```
arr1 is lexicographically smaller than arr2.
```
### Steps:
1. **Implement `Comparable<T>`**: The `Student` class must implement the
`Comparable<Student>` interface.
2. **Override `compareTo()`**: Inside the `Student` class, implement the
`compareTo()` method to define how two `Student` objects should be compared (e.g.,
by student ID, name, or grades).
### Example:
```java
import java.util.Arrays;
// Constructor
public Student(int id, String name) {
this.id = id;
this.name = name;
}
// Getters
public int getId() {
return id;
}
### Explanation:
1. **`Comparable<Student>`**: The `Student` class implements the `Comparable`
interface. In this example, students are compared based on their `id` field in the
`compareTo()` method.
2. **Lexicographical Comparison**: The `Arrays.compare()` method compares the two
arrays of `Student` objects element by element using the `compareTo()` method.
3. **Result**:
- If `students1` is lexicographically smaller than `students2` (based on
`Student`'s comparison logic), it returns a negative integer.
- If `students1` is lexicographically larger, it returns a positive integer.
- If both arrays are equal, it returns `0`.
In this case:
- The first two students in both arrays are identical (`101, "Alice"` and `102,
"Bob"`).
- The third students differ: `students1` has `103, "Charlie"`, while `students2`
has `104, "David"`. Since `103 < 104`, the first array is lexicographically
smaller.
```java
@Override
public int compareTo(Student other) {
return this.name.compareTo(other.name); // Compare by name
}
```
A synchronized method ensures that only one thread can execute the method at a time
for a particular object. You can synchronize both instance methods and static
methods.
When a method is declared as `synchronized`, the lock on the instance of the class
is used. This means that only one thread can execute any synchronized instance
method on the same object.
```java
public class SynchronizedExample {
```java
public class SynchronizedExample {
```java
public class SynchronizedBlockExample {
synchronized (lock) {
// Critical section of code that needs synchronization
System.out.println("Synchronized block is running.");
}
**Details:**
- **Object Locking:** The `synchronized (lock)` statement locks on the `lock`
object. Only one thread can hold the lock on this object at a time, thus allowing
only one thread to execute the synchronized block.
- **Granular Control:** By locking on a specific object, you can synchronize only
the critical section of code, potentially improving performance.
- **Scope of Lock:**
- **Synchronized Methods:** Locks the entire method, affecting all code within
the method.
- **Synchronized Blocks:** Locks only the specific block of code, allowing more
granular control over what is synchronized.
- **Flexibility:**
- **Synchronized Methods:** Easier to use but less flexible.
- **Synchronized Blocks:** Provide more control and can be used to synchronize on
different objects or parts of code.
In summary, you should use synchronized methods when you need to synchronize an
entire method, and synchronized blocks when you want to synchronize only a specific
part of your code for better performance.
==========================
Yes, you can have both synchronized methods and synchronized blocks within the same
class in Java. Combining both methods provides flexibility in controlling thread
access to shared resources.
Here's an example to illustrate how you can use both synchronized methods and
synchronized blocks in a class:
```java
public class SynchronizedExample {
synchronized (lock) {
// Critical section of code that needs synchronization
count++;
System.out.println("Synchronized block: count = " + count);
}
Here's how you might call these synchronized methods and blocks from another class:
```java
public class Main {
public static void main(String[] args) {
SynchronizedExample example = new SynchronizedExample();
### Explanation
### Summary
You can mix both synchronized methods and blocks in a class based on your
synchronization needs. By calling these methods and blocks as shown above, you
ensure that access to shared resources is managed properly to avoid data
inconsistency and race conditions.
=================
In Java, a synchronized block is used to control access to a particular section of
code within a method or a block. The scope of synchronized blocks is typically
confined to methods. However, there are some specific scenarios where synchronized
blocks can be used in constructors, and you cannot have synchronized blocks
directly at the class level (outside of methods).
Yes, you can have a synchronized block inside a constructor. This can be useful
when you need to ensure thread safety during the initialization of an object.
```java
public class SynchronizedConstructorExample {
public SynchronizedConstructorExample() {
// Synchronized block inside constructor
synchronized (lock) {
// Critical section code
count++;
System.out.println("Synchronized block inside constructor: count = " +
count);
}
}
In this example:
- The `synchronized (lock)` block inside the constructor ensures that only one
thread can execute the critical section of the constructor at a time, protecting
the initialization of the `count` variable.
You cannot have a synchronized block directly at the class level or outside of
methods or constructors. Synchronized blocks must be within methods or constructors
because they rely on a specific locking mechanism which is not applicable outside
these scopes.
**Valid Usage:**
- Inside Methods:
```java
public void someMethod() {
synchronized (lock) {
// Synchronized block inside method
}
}
```
- Inside Constructors:
```java
public SynchronizedConstructorExample() {
synchronized (lock) {
// Synchronized block inside constructor
}
}
```
**Invalid Usage:**
### Summary
```java
public class StringBuilderExample {
public static void main(String[] args) {
// Create a String
String str = "Hello, World!";
```java
public class StringBuilderExample {
public static void main(String[] args) {
// Create another StringBuilder
StringBuilder anotherSb = new StringBuilder("Initial Content");
```java
public class StringBuilderExample {
public static void main(String[] args) {
// Create a StringBuffer
StringBuffer buffer = new StringBuffer("Buffer Content");
### Explanation
1. **String as CharSequence:**
- The `StringBuilder` is initialized with a `String`. This is straightforward
because `String` implements `CharSequence`.
2. **StringBuilder as CharSequence:**
- The `StringBuilder` can be initialized with another `StringBuilder`. This
demonstrates how you can create a `StringBuilder` from another one.
3. **StringBuffer as CharSequence:**
- The `StringBuilder` can be initialized with a `StringBuffer`, another
`CharSequence` implementation.
### Summary
Assume you have a class `Employee` with fields for `id`, `dept`, and `sal`:
```java
public class Employee {
private int id;
private String dept;
private double sal;
// Constructor
public Employee(int id, String dept, double sal) {
this.id = id;
this.dept = dept;
this.sal = sal;
}
// Getters
public int getId() {
return id;
}
@Override
public String toString() {
return "Employee{id=" + id + ", dept='" + dept + "', sal=" + sal + "}";
}
}
```
To group employees by their department and then by their salary, you can use a
nested `Map` structure where the outer map groups by department and the inner map
groups by salary. Here’s how you can do it using Java 8 Streams:
```java
import java.util.*;
import java.util.stream.Collectors;
### Explanation
2. **`Collectors.groupingBy(Employee::getDept,
Collectors.groupingBy(Employee::getSal))`:**
- The first `groupingBy` collects employees into a map where the key is the
department (`Employee::getDept`).
- The second `groupingBy` is nested inside the first one, grouping employees by
salary (`Employee::getSal`) within each department.
The output will display employees grouped first by their department and then by
their salary. For example:
```
Department: IT
Salary: 60000.0 -> [Employee{id=1, dept='IT', sal=60000.0}, Employee{id=3,
dept='IT', sal=60000.0}]
Salary: 70000.0 -> [Employee{id=5, dept='IT', sal=70000.0}]
Department: HR
Salary: 50000.0 -> [Employee{id=2, dept='HR', sal=50000.0}]
Salary: 45000.0 -> [Employee{id=4, dept='HR', sal=45000.0}]
Department: Finance
Salary: 80000.0 -> [Employee{id=6, dept='Finance', sal=80000.0}]
```
This approach effectively organizes and displays the employees by their departments
and salaries using the power of Java 8 Streams and collectors.
===========================
To improve your code using functional interfaces and the method reference operator
(`::`), you can define a method that performs the squaring operation and then use
that method reference to instantiate the `Function` interface. This approach makes
the code more readable and separates the squaring logic from the lambda expression.
Here’s how you can rewrite the code using a functional interface and method
references:
First, create a static method that performs the squaring operation. This method
will be used with the method reference operator.
```java
package com.nareshtechhub12;
import java.util.function.Function;
### Explanation
1. **Method Reference (`SquareWithLambda::square`):**
- `SquareWithLambda::square` is a method reference that refers to the static
method `square` in the `SquareWithLambda` class. It is used to instantiate the
`Function` interface.
- Method references provide a concise and clear way to refer to methods without
using lambda expressions, improving code readability.
### Benefits
- **Readability:** Using method references can make the code more readable,
especially when the method logic is complex or when using the method multiple
times.
- **Separation of Concerns:** Separates the logic of squaring from its application,
making the main method cleaner.
By using method references, your code becomes more modular and easier to
understand, while still leveraging the power of functional programming in Java.
======================
The code snippet you've provided defines a lambda expression, but it doesn't
actually utilize it or demonstrate its functionality. To properly use a lambda
expression to calculate the length of a string, you should define a functional
interface (or use an existing one) and then apply the lambda expression.
Here's how you can write a complete program that uses a lambda expression to
calculate the length of a string:
```java
package com.nareshtechhub12;
import java.util.function.Function;
### Explanation
2. **Lambda Expression:**
- The lambda expression `s -> s.length()` takes a `String` (denoted by `s`) and
returns its length using the `length()` method.
### Output
When you run the above program, you will see the following output:
```
Length of 'Hello': 5
Length of 'NareshTechHub': 14
Length of 'Java': 4
```
### Summary
This structure allows you to easily reuse the string length logic in different
parts of your program, following functional programming principles.
==================
In Java, lambda expressions are typically used with functional interfaces, which
can be passed around and called as needed. Let's break down how to call lambda
methods, write static lambda methods, and call one lambda method from another.
```java
import java.util.function.Function;
```java
import java.util.function.Function;
You can indeed call one lambda expression from another by defining the first lambda
as a functional interface and then using it inside the second lambda.
```java
import java.util.function.Function;
### Summary
You can pass arguments to the `main` method via the command line. The arguments are
received as an array of `String` objects.
```java
public class CommandLineExample {
public static void main(String[] args) {
for (String arg : args) {
System.out.println(arg);
}
}
}
```
You can define methods that accept parameters. These parameters can be of any data
type (primitive or object).
```java
public class MethodParametersExample {
public static void greet(String name) {
System.out.println("Hello, " + name + "!");
}
The `Scanner` class can be used to take input from various sources, including
keyboard input.
```java
import java.util.Scanner;
```java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
If you create a graphical user interface (GUI) using Java Swing or JavaFX, you can
take input from text fields or other components.
```java
import javax.swing.*;
```java
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
In frameworks like Spring, you can use annotations to inject dependencies and
configure beans, which can include passing parameters.
### Summary
1. Command-Line Arguments
2. Method Parameters
3. User Input via `Scanner`
4. File Input
5. GUI Input
6. Properties File
7. Framework Annotations
Each method is suited for different use cases, allowing flexibility in how you can
handle input in Java applications.
========================
A functional interface in Java is defined as an interface that contains exactly
**one** abstract method. This characteristic allows it to be used as the assignment
target for lambda expressions and method references. Here’s a detailed breakdown of
the characteristics of functional interfaces:
2. **Default Methods:**
- A functional interface can have **multiple** default methods. Default methods
provide a way to add new methods to interfaces without breaking existing
implementations.
- Example:
```java
@FunctionalInterface
public interface MyFunctionalInterface {
void doSomething(); // single abstract method
3. **Static Methods:**
- A functional interface can also contain static methods. These methods belong
to the interface itself and are not tied to any instance of the interface.
- Example:
```java
@FunctionalInterface
public interface MyFunctionalInterface {
void doSomething(); // single abstract method
4. **Private Methods:**
- Since Java 9, interfaces can have private methods, which can be used to
encapsulate code that is used by default methods within the same interface.
- Example:
```java
@FunctionalInterface
public interface MyFunctionalInterface {
void doSomething(); // single abstract method
### Summary
### Summary
This structure allows you to build flexible and reusable interfaces while still
adhering to the single abstract method requirement that makes them functional
interfaces.
=====================
Functional interfaces play a crucial role in Java, especially with the introduction
of lambda expressions and the functional programming paradigm in Java 8. Here are
some key uses and benefits of functional interfaces:
Functional interfaces allow you to use lambda expressions, which provide a more
concise and readable way to implement single-method interfaces. This makes your
code cleaner and reduces boilerplate.
**Example:**
```java
@FunctionalInterface
public interface Calculator {
int calculate(int a, int b);
}
Functional interfaces enable the creation of higher-order functions, which can take
other functions as parameters or return them. This is essential for functional
programming concepts like mapping, filtering, and reducing collections.
**Example:**
```java
import java.util.function.Function;
By using functional interfaces and lambda expressions, you can enhance the
readability of your code. The intent of the code becomes clearer, as you can see
what functions are being applied without having to navigate through verbose class
definitions.
In GUI frameworks (like Swing or JavaFX), functional interfaces can be used for
event handling, making it easier to implement event listeners with a more concise
syntax.
**Example in GUI:**
```java
button.addActionListener(e -> System.out.println("Button clicked!"));
```
### Summary
In essence, while functional interfaces contain only one abstract method, their
flexibility and compatibility with lambda expressions make them a powerful tool for
writing clean, functional-style code in Java.
==================================
In Java, you cannot directly nest methods inside other methods, as Java does not
support nested method definitions. However, you can define methods inside a class,
and you can call one method from another within the same class.
Here's an example that demonstrates how to define multiple methods within a class
and call one method from another:
```java
public class MethodNestingExample {
public static void main(String[] args) {
MethodNestingExample example = new MethodNestingExample();
example.outerMethod(); // Call the outer method
}
// Outer method
public void outerMethod() {
System.out.println("This is the outer method.");
innerMethod(); // Call the inner method
}
// Inner method
public void innerMethod() {
System.out.println("This is the inner method.");
}
}
```
### Explanation
1. **Method Definitions:**
- Both `outerMethod` and `innerMethod` are defined within the same class,
`MethodNestingExample`.
2. **Calling Methods:**
- `outerMethod` calls `innerMethod` within its body. When `outerMethod` is
invoked from the `main` method, it subsequently calls `innerMethod`, resulting in
both methods being executed.
### Output
When you run the above program, you will see the following output:
```
This is the outer method.
This is the inner method.
```
### Summary
- **Direct Nesting:** Java does not allow direct nesting of method definitions
within one another.
- **Method Calls:** You can define multiple methods in a class and call one method
from another, effectively simulating a "nested" behavior.
- **Instance Methods:** You typically need to create an instance of the class to
call its instance methods, unless the methods are static.
This structure helps maintain code organization and allows for modular design,
making it easier to read and maintain.
======================
Yes, in Java, you can declare an interface inside a class. This is known as a
**nested interface**. A nested interface can be a member of a class, and it has
access to the members of the enclosing class, including private members.
```java
public class OuterClass {
// Nested interface
public interface NestedInterface {
void display();
}
### Explanation
### Summary
- You can declare an interface inside a class in Java, creating a nested interface.
- Nested interfaces can be public, private, protected, or package-private.
- They can be useful for logically grouping related functionality within a class.
```java
class Animal {
public void sound() {
System.out.println("Animal makes a sound");
}
}
### Explanation
- **Conciseness:** They allow you to write less code by combining class definition
and instantiation in one line.
- **Customization:** You can customize the behavior of the parent class without
creating a separate named subclass.
- **Local Scope:** They can access final or effectively final variables from their
enclosing scope.
### Summary
- Yes, you can create an anonymous class that extends a concrete class in Java.
- This allows for quick customization of the class behavior without the overhead of
creating a named subclass.
- Anonymous classes are often used in GUI applications, event handling, and in
places where a simple extension is needed.
========================================
Yes, you can define multiple anonymous inner classes within a class in Java. Each
anonymous inner class can extend a concrete class or implement an interface, and
you can create as many as you need within a single class.
Here's an example demonstrating how to define four anonymous inner classes inside a
single class:
```java
class Animal {
public void sound() {
System.out.println("Animal makes a sound");
}
}
// Anonymous class 2
Animal cat = new Animal() {
@Override
public void sound() {
System.out.println("Cat meows");
}
};
// Anonymous class 3
Animal cow = new Animal() {
@Override
public void sound() {
System.out.println("Cow moos");
}
};
// Anonymous class 4
Animal sheep = new Animal() {
@Override
public void sound() {
System.out.println("Sheep bleats");
}
};
### Explanation
3. **Method Calls:**
- We call the `sound()` method for each of the instances (`dog`, `cat`, `cow`,
and `sheep`), demonstrating the behavior defined in each anonymous class.
### Summary
- You can write as many anonymous inner classes as needed within a single class in
Java.
- Each can extend a concrete class or implement an interface, allowing for flexible
and concise code.
- This approach is often used for quick and temporary implementations, especially
in GUI applications and event handling scenarios.
===================
To call a static method from another class in Java, you simply need to use the
class name followed by the method name. Here's how you can do it step by step:
First, create a class that contains a static method. For example, let's call this
class `ClassA`.
```java
public class ClassA {
// Static method
public static void m1() {
System.out.println("Static method m1 called.");
}
}
```
Now, create another class (e.g., `ClassB`) from which you will call the static
method `m1` of `ClassA`.
```java
public class ClassB {
public static void main(String[] args) {
// Calling the static method from ClassA
ClassA.m1(); // Output: Static method m1 called.
}
}
```
### Explanation
- **Calling the Method:** In `ClassB`, you call `m1` using the class name `ClassA`
followed by a dot operator and the method name (`ClassA.m1()`).
### Summary
This approach allows you to easily access utility methods or shared functionality
across different classes in your Java application.
===================
You can call the `main` method defined in an interface just like you would call a
static method from any class. Here's how to do it:
### Example
```java
package com.nareshtechhub12;
Now, create another class (e.g., `MainCaller`) from which you will call the `main`
method of the `Interf` interface.
```java
package com.nareshtechhub12;
### Explanation
- **Calling the Interface Method:** In `MainCaller`, you call the `main` method of
the `Interf` interface using the syntax `Interf.main(args)`. This is valid because
`main` is a static method in the interface.
### Output
When you run the `MainCaller` class, the output will be:
```
Interface main method
```
### Summary
You can call a static method (including `main`) defined in an interface from
another class using the interface name followed by the method name. This allows for
flexibility in utilizing methods defined in interfaces without needing to create an
instance of the interface.
==================
In Java, an abstract class can contain both abstract methods (methods without a
body) and concrete methods (methods with an implementation). However, if an
abstract class has all concrete methods, it doesn't necessarily need to be declared
as abstract.
That said, here’s how you can create an abstract class with only concrete methods,
although it's a bit unusual:
```java
abstract class Shape {
// Concrete method
public void draw() {
System.out.println("Drawing the shape.");
}
### Explanation
3. **Main Method:**
- In the `Main` class, you create an instance of `Circle` and call the inherited
methods.
### Summary
- An abstract class can contain all concrete methods, but it must be declared as
abstract if it is not instantiated directly.
- You typically use abstract classes to provide a common base for subclasses, even
if they don't have abstract methods.
- In practice, it's more common for abstract classes to have a mix of abstract and
concrete methods to enforce certain behaviors in subclasses.
=====================
In Java, choosing between a **Predicate** and a **Function** often depends on what
you need to accomplish:
### Predicate
- **Purpose**: A `Predicate` is a functional interface that represents a single
argument function that returns a boolean value. It's mainly used for testing
conditions.
- **When to use**: Use a `Predicate` when you need to evaluate whether an element
meets certain criteria or conditions. For example, filtering collections based on
certain attributes.
**Example**:
```java
Predicate<String> isLongerThanFive = str -> str.length() > 5;
boolean result = isLongerThanFive.test("Hello, world!"); // true
```
### Function
- **Purpose**: A `Function` is a functional interface that represents a function
that takes one argument and produces a result. It’s not limited to returning
boolean values.
- **When to use**: Use a `Function` when you want to transform data, such as
mapping one type to another or applying a calculation.
**Example**:
```java
Function<String, Integer> stringLength = str -> str.length();
Integer length = stringLength.apply("Hello!"); // 6
```
### Summary
- Use **Predicate** for conditions and boolean tests.
- Use **Function** for transformations and computations.
By understanding your specific use case, you can choose the appropriate functional
interface to make your code cleaner and more expressive!
===========================
==========================END====================================================