Functional interface
Bilkul! Yahaan functional interfaces aur lambda expressions par ek poora blog-style article hai, jise aap jab chaahein padh aur revise kar sakte hain.
Java mein Functional Interfaces aur Lambda Expressions: Ek Complete Guide
Java, ek continuously evolve hone wali programming language hai, aur iske sabse powerful aur game-changing features mein se do hain Functional Interfaces aur Lambda Expressions. Agar aap modern Java programming mein expert banna chahte hain, toh in concepts ko samajhna bahut zaroori hai. Chaliye, inhein detail mein samajhte hain.
Functional Interface Kya Hai?
Sabse pehle, Functional Interface ko samajhte hain.
Definition: Ek Functional Interface Java mein ek aisa interface hota hai jismein sirf ek abstract method hota hai. Bas ek! Yahi iski pehchan hai.
Udaharan (Example):
Aapke diye gaye code se:
// 1. Contract (The Functional Interface)
// Yeh kehta hai: "Mujhe ek aisi implementation do jo do integer le (start, end)
// aur ek long (sum) return kare."
@FunctionalInterface
interface RangeSummer {
long sumRange(int start, int end);
}
Is RangeSummer
interface mein sirf ek abstract method hai: sumRange(int start, int end)
. Isliye, yeh ek functional interface hai.
@FunctionalInterface
Annotation:
Aapne dekha hoga ki RangeSummer
ke upar @FunctionalInterface
likha hai. Yeh annotation optional hai, lekin isko lagane se compiler yeh ensure karta hai ki aap galti se is interface mein ek se zyada abstract method add na kar dein. Agar aapne add kiya, toh compile-time error mil jayega. Yeh best practice hai iska istemal karna.
Key Takeaway: Functional interface ek blueprint hai ek single ‘functionality’ (ya ‘behavior’) ke liye.
Lambda Expression Kya Hai?
Ab jab hum functional interface ko samajh gaye hain, toh Lambda Expression ki baari aati hai.
Definition: Ek Lambda Expression functional interface ke ek-lauta abstract method ko implement karne ka ek shortcut, concise aur clean tareeka hai. Iske zariye aapko poori anonymous inner class banane ki zaroorat nahi padti.
Syntax: Lambda expressions ka basic syntax kuch aisa hota hai:
(parameters) -> expression
ya
(parameters) -> { statements; }
(parameters)
: Yeh functional interface ke abstract method ke parameters hain.->
: Isko “arrow operator” kehte hain. Yeh parameters ko method ki actual implementation se alag karta hai.expression
ya{ statements; }
: Yeh woh logic hai jo method ke andar execute hoga. Agar single expression hai, toh curly braces{}
aurreturn
keyword optional hain. Agar multiple statements hain, toh{}
aurreturn
(agar koi value return karni hai) mandatory hain.
Aapke Code Mein Iska Matlab:
// 2. Implementation (The Lambda Expression)
// Yeh us contract ko poora karta hai.
RangeSummer streamSummer = (start, end) -> IntStream.rangeClosed(start, end).asLongStream().sum();
Is line ko tod kar dekhte hain:
(start, end)
: YehsumRange
method ke parameters hain.->
: Yeh indicate karta hai ki yeh ek lambda expression hai.IntStream.rangeClosed(start, end).asLongStream().sum();
: Yeh woh logic hai josumRange
method ke andar chalega. Yehstart
seend
tak ke sabhi integers ka sum calculate karta hai.
Fayda: streamSummer
variable ab ek functional interface ka instance hai, jise aap bilkul ek normal variable ki tarah kisi bhi method mein pass kar sakte hain, jaisa aapne calculateSum(...)
mein kiya tha. Isse code bahut compact aur readable ho jata hai.
Examples aur Exercises se “Pro” Banein
Chaliye, kuch practical examples aur exercises ke saath in concepts ko aur mazboot karte hain.
Example 1: Simple String Operations
Hum ek functional interface banayenge jo ek string par operation karega.
import java.util.function.Function;
public class StringExample {
// Functional Interface Definition
@FunctionalInterface
interface StringOperator {
String operate(String input);
}
// Ek method jo is interface ko as a parameter leta hai
public static void processString(String text, StringOperator operator) {
String result = operator.operate(text);
System.out.println("Result: " + result);
}
public static void main(String[] args) {
String myName = "Gemini";
// Implementation 1: String ko Uppercase mein badalna
StringOperator toUpper = (s) -> s.toUpperCase();
processString(myName, toUpper); // Output: Result: GEMINI
// Implementation 2: String ko reverse karna
StringOperator toReverse = (s) -> new StringBuilder(s).reverse().toString();
processString(myName, toReverse); // Output: Result: inimeG
// Aap direct bhi pass kar sakte hain
processString("Hello World", (s) -> s.replace("World", "Java")); // Output: Result: Hello Java
// **Exercise 1 Solution:**
// Ek StringOperator lambda likhein jo di gayi string ke aage (processed) jod de.
StringOperator addProcessedSuffix = (s) -> s + " (processed)";
processString("Data", addProcessedSuffix); // Output: Result: Data (processed)
processString("Report", (s) -> s + " (processed)"); // Direct pass
}
}
Example 2: Number Checker (Generic Functional Interface)
Hum ek generic functional interface banayenge jo check karega ki koi value ek condition ko poora karti hai ya nahi.
public class CheckerExample {
// Generic Functional Interface
@FunctionalInterface
interface Checker<T> {
boolean test(T value);
}
public static void main(String[] args) {
// Implementation 1: Check karna ki number even hai ya nahi
Checker<Integer> isEven = (n) -> n % 2 == 0;
System.out.println("Is 10 even? " + isEven.test(10)); // Output: Is 10 even? true
System.out.println("Is 7 even? " + isEven.test(7)); // Output: Is 7 even? false
// Implementation 2: Check karna ki string khali (empty) hai ya nahi
Checker<String> isNotEmpty = (s) -> s != null && !s.isEmpty();
System.out.println("Is 'hello' not empty? " + isNotEmpty.test("hello")); // Output: Is 'hello' not empty? true
System.out.println("Is '' not empty? " + isNotEmpty.test("")); // Output: Is '' not empty? false
// **Exercise 2 Solution:**
// Ek Checker lambda likhein jo check kare ki number 100 se bada hai ya nahi.
Checker<Integer> isGreaterThan100 = (num) -> num > 100;
System.out.println("Is 50 greater than 100? " + isGreaterThan100.test(50)); // Output: Is 50 greater than 100? false
System.out.println("Is 150 greater than 100? " + isGreaterThan100.test(150)); // Output: Is 150 greater than 100? true
}
}
Example 3: Simple Calculator
Ek calculator banate hain jo do numbers par alag-alag operations karega.
public class CalculatorExample {
@FunctionalInterface
interface BinaryCalculator {
double calculate(double a, double b);
}
public static void main(String[] args) {
// Implementation 1: Addition
BinaryCalculator add = (a, b) -> a + b;
System.out.println("5 + 3 = " + add.calculate(5, 3)); // Output: 5 + 3 = 8.0
// Implementation 2: Multiplication
BinaryCalculator multiply = (a, b) -> a * b;
System.out.println("5 * 3 = " + multiply.calculate(5, 3)); // Output: 5 + 3 = 15.0
// Implementation 3: Division (with safety check)
BinaryCalculator divide = (a, b) -> {
if (b == 0) {
System.out.println("Error: Cannot divide by zero!");
return 0;
}
return a / b;
};
System.out.println("10 / 2 = " + divide.calculate(10, 2)); // Output: 10 / 2 = 5.0
System.out.println("10 / 0 = " + divide.calculate(10, 0)); // Output: Error... \n 10 / 0 = 0.0
// **Exercise 3 Solution:**
// Ek BinaryCalculator lambda likhein jo do numbers ka average (ausat) nikaale.
BinaryCalculator average = (a, b) -> (a + b) / 2.0;
System.out.println("Average of 10 and 20 = " + average.calculate(10, 20)); // Output: Average of 10 and 20 = 15.0
System.out.println("Average of 7 and 8 = " + average.calculate(7, 8)); // Output: Average of 7 and 8 = 7.5
}
}
Bonus Tip: Java ke Built-in Functional Interfaces
Java ne java.util.function
package mein bahut saare useful functional interfaces pehle se bana rakhe hain. Zyadatar cases mein, aapko apne khud ke functional interfaces banane ki zaroorat nahi padegi. Inka istemal karne se code aur bhi standard aur maintainable ho jata hai. Kuch common built-in functional interfaces hain:
Predicate<T>
: Ek valueT
leta hai aur ekboolean
return karta hai. (HamareChecker
jaisa).- Method:
boolean test(T t)
- Method:
Function<T, R>
: Ek valueT
leta hai aur doosri valueR
return karta hai. (HamareStringOperator
jaisa).- Method:
R apply(T t)
- Method:
Consumer<T>
: Ek valueT
leta hai aur kuch return nahi karta (void return type). JaiseSystem.out.println
mein use hota hai.- Method:
void accept(T t)
- Method:
Supplier<T>
: Koi value nahi leta, par ek valueT
return karta hai.- Method:
T get()
- Method:
BiFunction<T, U, R>
: Do valuesT
aurU
leta hai aur ek valueR
return karta hai. (HamareBinaryCalculator
jaisa).- Method:
R apply(T t, U u)
- Method:
Exercise 4: Built-in java.util.function.Predicate
ka Istemal
Task: Exercise 2 (Checker
) ko Java ke built-in java.util.function.Predicate
ka istemal karke dobara likhein.
import java.util.function.Predicate; // Import java.util.function.Predicate
public class PredicateCheckerExample {
public static void main(String[] args) {
// **Exercise 4 Solution:**
// Predicate<T> interface ka test method bhi boolean return karta hai aur ek T type ka argument leta hai.
// Ye hamare custom Checker<T> jaisa hi hai.
// Check karna ki number 100 se bada hai ya nahi using Predicate
Predicate<Integer> isGreaterThan100 = (num) -> num > 100;
System.out.println("Using Predicate:");
System.out.println("Is 50 greater than 100? " + isGreaterThan100.test(50)); // Output: Is 50 greater than 100? false
System.out.println("Is 150 greater than 100? " + isGreaterThan100.test(150)); // Output: Is 150 greater than 100? true
// Ek aur example: Check karna ki string "Java" hai
Predicate<String> isJava = (s) -> s.equals("Java");
System.out.println("Is 'Python' Java? " + isJava.test("Python")); // Output: Is 'Python' Java? false
System.out.println("Is 'Java' Java? " + isJava.test("Java")); // Output: Is 'Java' Java? true
}
}
Conclusion
Functional Interfaces aur Lambda Expressions Java 8 ke baad se modern Java programming ka ek anivaarya hissa ban gaye hain. Yeh aapke code ko concise, readable aur functional programming principles ke zyada kareeb banate hain. Stream API aur dusre new features ke saath inka istemal Java mein bahut common hai.
Aapke Liye Exercises ke Solutions:
Exercise 1: StringOperator Lambda
Task: Ek StringOperator
lambda likhein jo di gayi string ke aage "(processed)" jod de. Jaise agar input "Data" hai, to output "Data (processed)" aana chahiye. Isko processString
method mein use karke dekhein.
import java.util.function.Function;
public class StringExample {
// Functional Interface Definition
@FunctionalInterface
interface StringOperator {
String operate(String input);
}
// Ek method jo is interface ko as a parameter leta hai
public static void processString(String text, StringOperator operator) {
String result = operator.operate(text);
System.out.println("Result: " + result);
}
public static void main(String[] args) {
String myName = "Gemini";
// Implementation 1: String ko Uppercase mein badalna
StringOperator toUpper = (s) -> s.toUpperCase();
processString(myName, toUpper); // Output: Result: GEMINI
// Implementation 2: String ko reverse karna
StringOperator toReverse = (s) -> new StringBuilder(s).reverse().toString();
processString(myName, toReverse); // Output: Result: inimeG
// Aap direct bhi pass kar sakte hain
processString("Hello World", (s) -> s.replace("World", "Java")); // Output: Result: Hello Java
// **Exercise 1 Solution:**
StringOperator addProcessedSuffix = (s) -> s + " (processed)";
processString("Data", addProcessedSuffix); // Output: Result: Data (processed)
processString("Report", (s) -> s + " (processed)"); // Direct pass
}
}
Exercise 2: Checker Lambda (Number > 100)
Task: Ek Checker
lambda likhein jo check kare ki number 100 se bada hai ya nahi. Isko 50 aur 150 ke saath test karke dekhein.
public class CheckerExample {
// Generic Functional Interface
@FunctionalInterface
interface Checker<T> {
boolean test(T value);
}
public static void main(String[] args) {
// Implementation 1: Check karna ki number even hai ya nahi
Checker<Integer> isEven = (n) -> n % 2 == 0;
System.out.println("Is 10 even? " + isEven.test(10)); // Output: Is 10 even? true
System.out.println("Is 7 even? " + isEven.test(7)); // Output: Is 7 even? false
// Implementation 2: Check karna ki string khali (empty) hai ya nahi
Checker<String> isNotEmpty = (s) -> s != null && !s.isEmpty();
System.out.println("Is 'hello' not empty? " + isNotEmpty.test("hello")); // Output: Is 'hello' not empty? true
System.out.println("Is '' not empty? " + isNotEmpty.test("")); // Output: Is '' not empty? false
// **Exercise 2 Solution:**
Checker<Integer> isGreaterThan100 = (num) -> num > 100;
System.out.println("Is 50 greater than 100? " + isGreaterThan100.test(50)); // Output: Is 50 greater than 100? false
System.out.println("Is 150 greater than 100? " + isGreaterThan100.test(150)); // Output: Is 150 greater than 100? true
}
}
Exercise 3: BinaryCalculator Lambda (Average)
Task: Ek BinaryCalculator
lambda likhein jo do numbers ka average (ausat) nikaale. (a + b) / 2
.
public class CalculatorExample {
@FunctionalInterface
interface BinaryCalculator {
double calculate(double a, double b);
}
public static void main(String[] args) {
// Implementation 1: Addition
BinaryCalculator add = (a, b) -> a + b;
System.out.println("5 + 3 = " + add.calculate(5, 3)); // Output: 5 + 3 = 8.0
// Implementation 2: Multiplication
BinaryCalculator multiply = (a, b) -> a * b;
System.out.println("5 * 3 = " + multiply.calculate(5, 3)); // Output: 5 * 3 = 15.0
// Implementation 3: Division (with safety check)
BinaryCalculator divide = (a, b) -> {
if (b == 0) {
System.out.println("Error: Cannot divide by zero!");
return 0;
}
return a / b;
};
System.out.println("10 / 2 = " + divide.calculate(10, 2)); // Output: 10 / 2 = 5.0
System.out.println("10 / 0 = " + divide.calculate(10, 0)); // Output: Error... \n 10 / 0 = 0.0
// **Exercise 3 Solution:**
BinaryCalculator average = (a, b) -> (a + b) / 2.0; // Use 2.0 for double division
System.out.println("Average of 10 and 20 = " + average.calculate(10, 20)); // Output: Average of 10 and 20 = 15.0
System.out.println("Average of 7 and 8 = " + average.calculate(7, 8)); // Output: Average of 7 and 8 = 7.5
}
}
Exercise 4: Checker using java.util.function.Predicate
Task: Exercise 2 (Checker
) ko Java ke built-in java.util.function.Predicate
ka istemal karke dobara likhein.
import java.util.function.Predicate; // Import java.util.function.Predicate
public class PredicateCheckerExample {
public static void main(String[] args) {
// **Exercise 4 Solution:**
// Predicate<T> interface ka test method bhi boolean return karta hai aur ek T type ka argument leta hai.
// Ye hamare custom Checker<T> jaisa hi hai.
// Check karna ki number 100 se bada hai ya nahi using Predicate
Predicate<Integer> isGreaterThan100 = (num) -> num > 100;
System.out.println("Using Predicate:");
System.out.println("Is 50 greater than 100? " + isGreaterThan100.test(50)); // Output: Is 50 greater than 100? false
System.out.println("Is 150 greater than 100? " + isGreaterThan100.test(150)); // Output: Is 150 greater than 100? true
// Ek aur example: Check karna ki string "Java" hai
Predicate<String> isJava = (s) -> s.equals("Java");
System.out.println("Is 'Python' Java? " + isJava.test("Python")); // Output: Is 'Python' Java? false
System.out.println("Is 'Java' Java? " + isJava.test("Java")); // Output: Is 'Java' Java? true
}
}
Umeed hai ki in solutions ne aapko functional interfaces aur lambda expressions ki gehri samajh di hogi. Aapne dekha ki kaise custom functional interfaces bana sakte hain aur kaise Java ke built-in interfaces (Predicate
, Function
, Consumer
, Supplier
) hamare code ko aur bhi concise aur expressive bana dete hain.
Agar aapke paas aur koi sawaal hai ya aap kuch aur topics par practice karna chahte hain, to zaroor batayein!