Java Functional Programming হল একটি প্রোগ্রামিং প্যারাডাইম যা ফাংশনকে প্রথম শ্রেণীর নাগরিক হিসেবে ব্যবহার করে। এর মাধ্যমে আপনি ফাংশনগুলোকে আর্গুমেন্ট হিসেবে পাস করতে পারেন, রিটার্ন ভ্যালু হিসেবে ব্যবহার করতে পারেন, এবং অন্যান্য ফাংশনাল অপারেশন যেমন ম্যাপিং, ফিল্টারিং, এবং রিডুসিং করতে পারেন।
Functional Interfaces Java Functional Programming-এর একটি মৌলিক ধারণা। ফাংশনাল ইন্টারফেস হল সেই ইন্টারফেস যা একটি মাত্র抽ক ফাংশন সংজ্ঞায়িত করে, অর্থাৎ একমাত্র抽ক (abstract) মেথড থাকে। এই ধরনের ইন্টারফেসগুলি ল্যাম্বডা এক্সপ্রেশন এবং মেথড রেফারেন্সের জন্য ব্যবহার করা হয়, যা Java 8 এবং পরবর্তী ভার্সনে ফাংশনাল প্রোগ্রামিং ধারণা বাস্তবায়ন করতে সহায়তা করে।
Functional Interface এর ধারণা
Java 8-এ @FunctionalInterface অ্যানোটেশন যোগ করা হয়েছে যা নিশ্চিত করে যে, একটি ইন্টারফেসে একটি মাত্র抽ক মেথড রয়েছে এবং সেটি ফাংশনাল ইন্টারফেস হিসেবে ব্যবহার করা যেতে পারে।
যদিও Java তে Functional Interface এর জন্য কোনও বাধ্যবাধকতা নেই, তবে এই অ্যানোটেশনটি ব্যবহার করা ইচ্ছামত এবং পরিষ্কারভাবে ইন্টারফেসটি ফাংশনাল হিসেবে চিহ্নিত করতে সাহায্য করে। যদি আপনি @FunctionalInterface অ্যানোটেশন ব্যবহার করেন, তবে Java কম্পাইলার নিশ্চিত করবে যে ওই ইন্টারফেসে একটাই抽ক মেথড আছে।
Functional Interface এর উদাহরণ
১. ব্যাসিক Functional Interface Example
@FunctionalInterface
public interface MyFunctionalInterface {
// একমাত্র抽ক মেথড
void sayHello();
}
এই ইন্টারফেসে sayHello() নামক একটি抽ক মেথড রয়েছে, যেটি ফাংশনাল ইন্টারফেসের জন্য উপযুক্ত।
২. Lambda Expression ব্যবহার করা
ল্যাম্বডা এক্সপ্রেশন ব্যবহার করে আপনি Functional Interface এর抽ক মেথডের একটি ইমপ্লিমেন্টেশন প্রদান করতে পারেন:
public class Main {
public static void main(String[] args) {
// Lambda Expression ব্যবহার করা
MyFunctionalInterface myFunc = () -> System.out.println("Hello, World!");
myFunc.sayHello(); // Output: Hello, World!
}
}
এখানে, MyFunctionalInterface ইন্টারফেসের sayHello() মেথডে ল্যাম্বডা এক্সপ্রেশন দিয়ে ইমপ্লিমেন্টেশন প্রদান করা হয়েছে।
Java Built-in Functional Interfaces
Java 8 এর পর থেকে, অনেক built-in functional interfaces Java Collections Framework-এ অন্তর্ভুক্ত করা হয়েছে, যা আপনাকে সহজে functional programming এর ধারণা বাস্তবায়ন করতে সাহায্য করে। কিছু জনপ্রিয় built-in functional interfaces:
Predicate<T>:- Purpose: একটি একক ইনপুটের জন্য
booleanরিটার্ন করে। - Method:
boolean test(T t) - Usage: ফিল্টারিং এবং শর্তাবলী চেক করার জন্য।
উদাহরণ:
Predicate<Integer> isEven = num -> num % 2 == 0; System.out.println(isEven.test(4)); // Output: true- Purpose: একটি একক ইনপুটের জন্য
Function<T, R>:- Purpose: একটি ইনপুট অ্যারগুমেন্ট থেকে একটি আউটপুট প্রদান করে।
- Method:
R apply(T t) - Usage: ট্রান্সফর্মেশন অপারেশন করতে।
উদাহরণ:
Function<String, Integer> stringLength = str -> str.length(); System.out.println(stringLength.apply("Hello")); // Output: 5Consumer<T>:- Purpose: একটি ইনপুট নিয়ে কোনো ভ্যালু রিটার্ন না করে, কোনো অপারেশন সম্পাদন করে।
- Method:
void accept(T t) - Usage: ইনপুট ভ্যালু গ্রহণ করে, কোনো অপারেশন সম্পাদন করতে।
উদাহরণ:
Consumer<String> printString = str -> System.out.println(str); printString.accept("Hello, World!"); // Output: Hello, World!Supplier<T>:- Purpose: কোনো ইনপুট ছাড়াই আউটপুট প্রদান করে।
- Method:
T get() - Usage: কোনো ভ্যালু সরবরাহ করার জন্য।
উদাহরণ:
Supplier<Double> randomValue = () -> Math.random(); System.out.println(randomValue.get()); // Output: Random numberUnaryOperator<T>:- Purpose:
Function<T, T>এর একটি বিশেষ রূপ, যেখানে ইনপুট এবং আউটপুট একই টাইপের হয়। - Method:
T apply(T t) - Usage: একক ভ্যালুর ট্রান্সফর্মেশন।
উদাহরণ:
UnaryOperator<Integer> square = num -> num * num; System.out.println(square.apply(5)); // Output: 25- Purpose:
BinaryOperator<T>:- Purpose:
BiFunction<T, T, T>এর একটি বিশেষ রূপ, যেখানে দুটি ইনপুট এবং একটি আউটপুট একই টাইপের হয়। - Method:
T apply(T t1, T t2) - Usage: দুটি ভ্যালুর উপর অপারেশন করতে।
উদাহরণ:
BinaryOperator<Integer> add = (a, b) -> a + b; System.out.println(add.apply(5, 10)); // Output: 15- Purpose:
Functional Interface এবং Lambda Expressions এর সুবিধা
- Concise Code: ল্যাম্বডা এক্সপ্রেশন ব্যবহার করে কোড সংক্ষিপ্ত এবং পরিষ্কার হয়। একে Anonymous Functions বলা হয়, কারণ এতে নামকরণ করা ফাংশন থাকে না।
- Readability: ফাংশনাল প্রোগ্রামিং কোডে এক্সপ্রেশন সহজ করে তোলে, যা বোঝা সহজ এবং রক্ষণাবেক্ষণ করা সহজ।
- Higher Order Functions: ল্যাম্বডা এক্সপ্রেশন এবং ফাংশনাল ইন্টারফেসের মাধ্যমে আপনি ফাংশনগুলোকে আর্গুমেন্ট হিসেবে পাস করতে পারেন এবং রিটার্নও করতে পারেন, যা higher-order functions তৈরি করতে সাহায্য করে।
- Parallelism and Streams: ফাংশনাল প্রোগ্রামিং Java 8 থেকে
Stream APIদিয়ে যুক্ত হয়েছে, যা প্যারালাল প্রসেসিং এবং ডেটা প্রক্রিয়াকরণের জন্য খুবই কার্যকর।
সংক্ষেপে:
Functional Interfaces হল Java 8 এবং পরবর্তী সংস্করণের একটি শক্তিশালী বৈশিষ্ট্য, যা ফাংশনাল প্রোগ্রামিং ধারণাকে সমর্থন করে। এগুলো মূলত একটি抽ক মেথড বিশিষ্ট ইন্টারফেস, এবং সেগুলির সাথে ল্যাম্বডা এক্সপ্রেশন ব্যবহার করে আপনি ফাংশনাল প্রোগ্রামিংয়ের সুবিধা গ্রহণ করতে পারেন। Java 8 এবং পরবর্তী সংস্করণে Predicate, Function, Consumer, Supplier, UnaryOperator, BinaryOperator সহ বেশ কিছু বিল্ট-ইন ফাংশনাল ইন্টারফেস রয়েছে, যা কার্যকরভাবে ফাংশনাল প্রোগ্রামিং প্রয়োগে সাহায্য করে।
Java Functional Programming-এ Functional Interface একটি গুরুত্বপূর্ণ ধারণা, যা Java 8 থেকে এসেছে। এটি একটি interface যা শুধুমাত্র একটি abstract method ধারণ করে। ফাংশনাল ইন্টারফেস Java-এ ফাংশনাল প্রোগ্রামিং এর মূল ধারণাগুলির মধ্যে একটি, এবং এটি lambda expressions এবং method references এর সাথে ব্যবহৃত হয়। Functional Interface এর মূল উদ্দেশ্য হল first-class functions তৈরি করা যা Java-তে ফাংশনাল প্রোগ্রামিং ধারণাকে কার্যকর করে তোলে।
এখানে Functional Interface এর ধারণা এবং উদাহরণ দেওয়া হচ্ছে।
1. Functional Interface এর সংজ্ঞা
Functional Interface হল এমন একটি ইন্টারফেস যা শুধুমাত্র একটি abstract method রাখে। এই একক মেথডটি lambda expressions অথবা method references এর মাধ্যমে functional style পদ্ধতিতে কার্যকর করা যেতে পারে। ফাংশনাল ইন্টারফেসের মধ্যে default methods এবং static methods থাকতে পারে, কিন্তু abstract methods সর্বোচ্চ একটিই থাকতে পারে।
@FunctionalInterface অ্যানোটেশন
যদিও একটি ইন্টারফেস শুধুমাত্র একটি মেথড থাকা সত্ত্বেও, আপনি চাইলে @FunctionalInterface অ্যানোটেশন ব্যবহার করে এটি স্পষ্টভাবে একটি Functional Interface হিসেবে চিহ্নিত করতে পারেন। এটি optional, তবে এটি ইন্টারফেসটির কার্যকরীতা নিশ্চিত করে এবং ভুল ভাবে একাধিক abstract methods যুক্ত করা থেকে বাধা দেয়।
@FunctionalInterface
public interface MyFunctionalInterface {
void myMethod(); // Abstract method
// You can have default and static methods, but no other abstract methods
default void defaultMethod() {
System.out.println("This is a default method");
}
static void staticMethod() {
System.out.println("This is a static method");
}
}
এখানে, MyFunctionalInterface একটি Functional Interface যা শুধুমাত্র একটি abstract method (myMethod()) ধারণ করে এবং এর সাথে default ও static methods অন্তর্ভুক্ত আছে।
2. Functional Interface এর ব্যবহার
Java-এ Functional Interface মূলত lambda expressions এবং method references ব্যবহার করার জন্য ডিজাইন করা হয়েছে। এই ইন্টারফেসগুলি ক্লাসের মেথডকে ফাংশন হিসেবে পাস করার সক্ষমতা প্রদান করে।
Lambda Expression এর মাধ্যমে Functional Interface ব্যবহার
@FunctionalInterface
public interface Calculator {
int add(int a, int b); // Abstract method to add two numbers
}
public class LambdaExample {
public static void main(String[] args) {
// Using lambda expression to implement the add method
Calculator calculator = (a, b) -> a + b;
System.out.println("Sum: " + calculator.add(5, 3)); // Output: Sum: 8
}
}
এখানে, Calculator একটি Functional Interface, এবং lambda expression ব্যবহার করে add মেথডের কার্যকারিতা বাস্তবায়ন করা হয়েছে।
Method Reference এর মাধ্যমে Functional Interface ব্যবহার
Method references হল একটি শর্টকাট পদ্ধতি যা একটি মেথডকে ফাংশন হিসেবে পাস করার জন্য ব্যবহৃত হয়। এটি lambda expressions এর তুলনায় আরো সংক্ষিপ্ত এবং পাঠযোগ্য।
@FunctionalInterface
public interface Printer {
void printMessage(String message);
}
public class MethodReferenceExample {
public static void printUpperCase(String message) {
System.out.println(message.toUpperCase());
}
public static void main(String[] args) {
// Using method reference to implement the printMessage method
Printer printer = MethodReferenceExample::printUpperCase;
printer.printMessage("hello world"); // Output: HELLO WORLD
}
}
এখানে, MethodReferenceExample::printUpperCase একটি method reference যা Printer ইন্টারফেসের printMessage মেথডকে কার্যকর করছে।
3. Functional Interface এর সুবিধা
Functional Interface ব্যবহারের কয়েকটি গুরুত্বপূর্ণ সুবিধা আছে, যা Java Functional Programming-এ অত্যন্ত সহায়ক হয়:
- Code Readability: Functional interfaces এবং lambda expressions ব্যবহার করলে কোড আরো সংক্ষিপ্ত এবং পড়তে সহজ হয়। আপনি কম কোডে একটি ফাংশনাল অপারেশন সম্পাদন করতে পারেন।
- Lambda Expressions: Functional interfaces lambda expressions এর মাধ্যমে ফাংশনকে পাস করা এবং পরিচালনা করা সহজ করে তোলে।
- Higher-order Functions: Functional interfaces সাধারণত higher-order functions এর জন্য ব্যবহৃত হয়, যেখানে একটি ফাংশন অন্য ফাংশনকে আর্গুমেন্ট হিসেবে নেয় অথবা একটি ফাংশন রিটার্ন করে।
- Improved Flexibility: Functional interfaces Java-তে functional programming ধারণা বাস্তবায়নে সহায়তা করে এবং আরও নমনীয় ও শক্তিশালী অ্যাপ্লিকেশন ডেভেলপমেন্টকে সম্ভব করে তোলে।
- Integration with Streams API: Functional Interfaces Streams API-এর সাথে ব্যবহার করে ডেটা প্রসেসিং সহজ করে তোলে।
filter(),map(),reduce()সহ বিভিন্ন স্ট্রিম অপারেশনগুলির মাধ্যমে ফাংশনাল ইন্টারফেস ব্যবহার করা হয়।
4. Java Functional Interface এর কিছু উদাহরণ
4.1. Runnable Interface
@FunctionalInterface
public interface Runnable {
void run();
}
public class RunnableExample {
public static void main(String[] args) {
// Using lambda expression
Runnable runnable = () -> System.out.println("Running task...");
runnable.run(); // Output: Running task...
}
}
4.2. Comparator Interface
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2); // Abstract method to compare two objects
// Default methods can also be present
default Comparator<T> reversed() {
return (o1, o2) -> compare(o2, o1);
}
}
public class ComparatorExample {
public static void main(String[] args) {
Comparator<Integer> comparator = (a, b) -> Integer.compare(a, b);
System.out.println(comparator.compare(5, 3)); // Output: 1
}
}
4.3. Consumer Interface
@FunctionalInterface
public interface Consumer<T> {
void accept(T t); // Abstract method to consume an object
// Default method
default Consumer<T> andThen(Consumer<? super T> after) {
return (T t) -> { accept(t); after.accept(t); };
}
}
public class ConsumerExample {
public static void main(String[] args) {
Consumer<String> printConsumer = (s) -> System.out.println(s);
printConsumer.accept("Hello, Functional Interface!"); // Output: Hello, Functional Interface!
}
}
Functional Interface Java Functional Programming এর একটি শক্তিশালী এবং গুরুত্বপূর্ণ অংশ। এটি আপনাকে lambda expressions এবং method references ব্যবহার করে সহজে এবং কার্যকরভাবে ফাংশনাল প্রোগ্রামিং করতে সাহায্য করে। Java 8 থেকে এটি অনেক গুরুত্বপূর্ণ ফিচারের মধ্যে একটি হয়ে দাঁড়িয়েছে, এবং এটি functional programming paradigms এর সাথে Java কোডকে অধিক কার্যকরী, সংক্ষিপ্ত, এবং রক্ষণাবেক্ষণযোগ্য করে তোলে।
Functional Interface Java-তে higher-order functions, stream processing, এবং lazy evaluation সহ আরও অনেক ফিচারের সহায়ক, এবং এটি আপনার অ্যাপ্লিকেশন বা কোডের কার্যকারিতা উন্নত করতে সাহায্য করে।
Java 8 এ @FunctionalInterface অ্যানোটেশনটি একটি নতুন ফিচার হিসেবে যোগ করা হয়েছে, যা Functional Interface নির্দেশ করতে ব্যবহৃত হয়। ফাংশনাল ইন্টারফেসের মূল উদ্দেশ্য হল এমন একটি ইন্টারফেস তৈরি করা যা একটি মাত্র অ্যাবস্ট্র্যাক্ট মেথড ধারণ করে। এর মাধ্যমে, Java 8 এর Lambda Expressions এবং Method References এর সুবিধা গ্রহণ করা সম্ভব হয়।
যেহেতু Java 8 থেকে Lambda Expressions সমর্থিত, একমাত্র ফাংশনাল ইন্টারফেসগুলোই এই ফিচার ব্যবহার করতে পারে। @FunctionalInterface অ্যানোটেশন ইন্টারফেসটি ফাংশনাল ইন্টারফেস হিসেবে চিহ্নিত করে, যা কোডের পরিষ্কারতা এবং ভুল এড়ানোর জন্য সহায়ক।
@FunctionalInterface Annotation এর ধারণা:
- Functional Interface: এটি এমন একটি ইন্টারফেস যা শুধুমাত্র একটি অ্যাবস্ট্র্যাক্ট মেথড থাকে, এবং এটি Lambda Expressions অথবা Method References এর মাধ্যমে প্রয়োগ করা যেতে পারে।
@FunctionalInterfaceঅ্যানোটেশন: এই অ্যানোটেশনটি শুধুমাত্র ফাংশনাল ইন্টারফেসকে চিহ্নিত করে। যদি আপনি একটি ইন্টারফেসে এই অ্যানোটেশন ব্যবহার করেন, তবে Java কন্টেইনার এটি নিশ্চিত করবে যে সেই ইন্টারফেসে শুধুমাত্র একটি অ্যাবস্ট্র্যাক্ট মেথড আছে। যদি আপনি আরও এক্সট্রা অ্যাবস্ট্র্যাক্ট মেথড যুক্ত করেন, তবে এটি একটি কম্পাইল টাইম এরর দিবে।
@FunctionalInterface অ্যানোটেশন ব্যবহার:
@FunctionalInterface অ্যানোটেশনটি একটি ইন্টারফেসের উপরে যোগ করতে হয়। এই অ্যানোটেশনটি ব্যবহৃত হলে, ইন্টারফেসে অবশ্যই একটি অ্যাবস্ট্র্যাক্ট মেথড থাকতে হবে। পাশাপাশি, default এবং static মেথড থাকলেও কোনো সমস্যা নেই, কারণ এগুলি অ্যাবস্ট্র্যাক্ট মেথডের মধ্যে গণ্য হয় না।
@FunctionalInterface উদাহরণ:
@FunctionalInterface
public interface Calculator {
int add(int a, int b); // Single abstract method (SAM)
// Default method (Not counted as abstract)
default int multiply(int a, int b) {
return a * b;
}
// Static method (Not counted as abstract)
static int subtract(int a, int b) {
return a - b;
}
}
এখানে, Calculator ইন্টারফেস একটি Functional Interface কারণ এতে শুধুমাত্র একটি অ্যাবস্ট্র্যাক্ট মেথড (add) রয়েছে।
multiplyএকটি default method এবংsubtractএকটি static method, যা abstract মেথড হিসেবে গণ্য হয় না।
Lambda Expression এর সাথে ব্যবহার:
ফাংশনাল ইন্টারফেসের সাথে Lambda Expression ব্যবহার করা হয় যা কোডকে আরও সংক্ষিপ্ত এবং পরিষ্কার করে।
public class CalculatorDemo {
public static void main(String[] args) {
// Lambda Expression for 'add' method
Calculator calculator = (a, b) -> a + b;
// Using the method
System.out.println("Addition: " + calculator.add(5, 3)); // Output: 8
// Calling default method
System.out.println("Multiplication: " + calculator.multiply(5, 3)); // Output: 15
// Calling static method
System.out.println("Subtraction: " + Calculator.subtract(5, 3)); // Output: 2
}
}
এখানে, Lambda Expression (a, b) -> a + b ব্যবহার করে Calculator ইন্টারফেসের add মেথডটি বাস্তবায়ন করা হয়েছে।
@FunctionalInterface এর সুবিধা:
- Compile-time Check:
@FunctionalInterfaceঅ্যানোটেশন ব্যবহারের ফলে কম্পাইলারটি নিশ্চিত করে যে ইন্টারফেসটি সঠিকভাবে ফাংশনাল ইন্টারফেস হিসেবে চিহ্নিত করা হয়েছে এবং এতে শুধুমাত্র একটি অ্যাবস্ট্র্যাক্ট মেথড রয়েছে। যদি আরো এক্সট্রা অ্যাবস্ট্র্যাক্ট মেথড থাকে, তবে এটি কম্পাইল টাইমে একটি ত্রুটি (error) প্রদর্শন করবে।
- Clear Intent:
@FunctionalInterfaceঅ্যানোটেশন কোডের উদ্দেশ্যকে স্পষ্ট করে তোলে। এটি নির্দেশ করে যে এই ইন্টারফেসটি একটি ফাংশনাল ইন্টারফেস এবং শুধুমাত্র একটি অ্যাবস্ট্র্যাক্ট মেথড থাকবে।
- Readability:
- ফাংশনাল ইন্টারফেস ব্যবহার করার মাধ্যমে কোড আরও পরিষ্কার এবং সহজে রিডেবল হয়, কারণ এর মধ্যে একাধিক অ্যাবস্ট্র্যাক্ট মেথড থাকবে না, যা কোডের জটিলতা বাড়ায়।
- Lambda Expressions:
- ফাংশনাল ইন্টারফেস ব্যবহার করে আপনি Lambda Expressions এবং Method References এর মাধ্যমে আরও সংক্ষিপ্ত এবং কার্যকর কোড লেখতে পারবেন।
@FunctionalInterface অ্যানোটেশন সম্পর্কিত কিছু নিয়ম:
- একটি মাত্র অ্যাবস্ট্র্যাক্ট মেথড থাকতে হবে: ফাংশনাল ইন্টারফেসে শুধুমাত্র একটি অ্যাবস্ট্র্যাক্ট মেথড থাকতে হবে। আপনি অন্যান্য মেথড যেমন default এবং static মেথড রাখতে পারেন, তবে তা abstract হিসেবে গণ্য হবে না।
@FunctionalInterfaceঅ্যানোটেশন ব্যবহার ঐচ্ছিক: @FunctionalInterface অ্যানোটেশনটি ব্যবহার করা অবশ্যই জরুরি নয়। যদি আপনি ইন্টারফেসে শুধুমাত্র একটি অ্যাবস্ট্র্যাক্ট মেথড রাখেন, তবে Java নিজেই সেটিকে ফাংশনাল ইন্টারফেস হিসেবে বিবেচনা করবে। তবে, অ্যানোটেশনটি ব্যবহার করলে কম্পাইলার চেক করবে যে এটি একটি ফাংশনাল ইন্টারফেস।
সারাংশ:
@FunctionalInterface অ্যানোটেশনটি Java 8 এর একটি গুরুত্বপূর্ণ বৈশিষ্ট্য যা ফাংশনাল ইন্টারফেস চিহ্নিত করতে ব্যবহৃত হয়। এটি একটি ইন্টারফেসের মধ্যে শুধুমাত্র একটি অ্যাবস্ট্র্যাক্ট মেথড থাকতে হবে তা নিশ্চিত করে এবং Lambda Expressions বা Method References এর সুবিধা গ্রহণ করতে সাহায্য করে। ফাংশনাল ইন্টারফেস ব্যবহারের মাধ্যমে আপনি Java-তে ফাংশনাল প্রোগ্রামিংয়ের সুবিধা নিতে পারেন, যেমন কোডের মডুলারিটি, রিডেবিলিটি, এবং টেস্টেবিলিটি উন্নত করা।
Java Functional Programming হল একটি প্রোগ্রামিং প্যারাডাইম যেখানে ফাংশনগুলি প্রথম শ্রেণীর নাগরিক (first-class citizens) হিসেবে ব্যবহৃত হয়। Java 8 থেকে Functional Interfaces এবং Lambda Expressions ইন্ট্রডিউস করা হয়েছে যা ফাংশনাল প্রোগ্রামিংয়ের ধারণাকে Java তে বাস্তবায়িত করেছে।
Functional Interfaces এমন interfaces, যেগুলির শুধুমাত্র একটি abstract method থাকে, এবং এগুলি lambda expressions এবং method references ব্যবহার করে আরও সহজভাবে কাজে লাগানো যায়। Java এর কিছু বিল্ট-ইন Functional Interfaces রয়েছে যা বিশেষ করে Runnable, Callable, এবং Comparator।
নিচে আমরা এই তিনটি Functional Interface (Runnable, Callable, Comparator) সম্পর্কে বিস্তারিত জানব এবং তাদের ব্যবহার উদাহরণসহ দেখব।
1. Runnable Interface
Runnable হল একটি Functional Interface যা java.lang প্যাকেজে অবস্থিত এবং এর একটি একমাত্র run() মেথড থাকে। এটি threading ব্যবস্থাপনায় ব্যবহৃত হয়, যেখানে run() মেথডের মধ্যে থ্রেডের কার্যক্রম নির্ধারণ করা হয়।
Runnable Interface এর বৈশিষ্ট্য:
- এটি কোন আর্গুমেন্ট নেয় না এবং কোন ভ্যালু রিটার্নও করে না।
- এটি সাধারণত multithreading বা asynchronous tasks এর জন্য ব্যবহৃত হয়।
Runnable Interface উদাহরণ (lambda expression):
public class RunnableExample {
public static void main(String[] args) {
// Using Runnable with a Lambda Expression
Runnable task = () -> {
System.out.println("Running in a separate thread");
};
// Running the task using a thread
Thread thread = new Thread(task);
thread.start();
}
}
এখানে, Runnable interface এর run() মেথড একটি lambda expression দিয়ে সংজ্ঞায়িত করা হয়েছে এবং Thread এ চলানো হয়েছে।
2. Callable Interface
Callable হল একটি Functional Interface যা java.util.concurrent প্যাকেজে অবস্থিত এবং এর মধ্যে একটি মাত্র call() মেথড থাকে। Callable interface এর মেইন পার্থক্য হল যে এটি Runnable এর তুলনায় একটি ভ্যালু রিটার্ন করে এবং এটি Exception থ্রো করতে পারে।
Callable Interface এর বৈশিষ্ট্য:
- Callable interface এর
call()মেথড একটি value রিটার্ন করে, যেখানে Runnable কোন ভ্যালু রিটার্ন করে না। - এটি exceptions handle করতে সক্ষম, যা Runnable এর ক্ষেত্রে সম্ভব নয়।
Callable Interface উদাহরণ (lambda expression):
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class CallableExample {
public static void main(String[] args) throws Exception {
// Using Callable with a Lambda Expression
Callable<Integer> task = () -> {
// Simulating some computation
return 10 + 20;
};
// Wrapping the Callable in a FutureTask
FutureTask<Integer> futureTask = new FutureTask<>(task);
// Running the task in a new thread
Thread thread = new Thread(futureTask);
thread.start();
// Getting the result
System.out.println("Result: " + futureTask.get()); // Output: Result: 30
}
}
এখানে, Callable interface এর call() মেথড একটি lambda expression দিয়ে সংজ্ঞায়িত করা হয়েছে এবং FutureTask ব্যবহার করে থ্রেডে রান করা হয়েছে। get() মেথডের মাধ্যমে রিটার্ন ভ্যালু পাওয়া যাচ্ছে।
3. Comparator Interface
Comparator হল একটি Functional Interface যা java.util প্যাকেজে অবস্থিত এবং এটি two-object comparison করার জন্য ব্যবহৃত হয়। compare(T o1, T o2) মেথড দিয়ে এটি দুটি অবজেক্টের তুলনা করে এবং সেই অনুযায়ী তাদের সাজানো বা অর্ডার করা হয়।
Comparator Interface এর বৈশিষ্ট্য:
- এটি দুটি অবজেক্টের তুলনা করে এবং একটি negative, zero, বা positive ভ্যালু রিটার্ন করে।
- সাধারণত এটি sorting এবং ordering এর জন্য ব্যবহৃত হয়।
Comparator Interface উদাহরণ (lambda expression):
import java.util.Arrays;
import java.util.Comparator;
public class ComparatorExample {
public static void main(String[] args) {
// Sample data
String[] names = {"Alice", "Bob", "Charlie", "David"};
// Using Comparator with Lambda Expression to sort alphabetically
Arrays.sort(names, (name1, name2) -> name1.compareTo(name2));
// Printing sorted names
System.out.println(Arrays.toString(names)); // Output: [Alice, Bob, Charlie, David]
}
}
এখানে, Comparator interface এর compare() মেথড একটি lambda expression দিয়ে সংজ্ঞায়িত করা হয়েছে এবং Arrays.sort() এর মাধ্যমে তালিকা সাজানো হয়েছে।
Runnable, Callable, Comparator এর মধ্যে পার্থক্য:
| Feature | Runnable | Callable | Comparator |
|---|---|---|---|
| Package | java.lang | java.util.concurrent | java.util |
| Methods | void run() | V call() | int compare(T o1, T o2) |
| Return Value | No return value | Returns a value of type V | Returns an integer (-ve, 0, +ve) |
| Exception Handling | Does not throw exceptions | Can throw exceptions | Does not throw exceptions |
| Usage | Used for threads without result | Used for threads that return a result | Used for comparing two objects |
| Default Implementations | Default implementations are available | Default implementations are available | No default implementations |
সারাংশ:
- Runnable: এই interface ব্যবহৃত হয় যখন আপনি থ্রেডে কোনো কাজ চালাতে চান, কিন্তু কাজের শেষে কোনো ভ্যালু রিটার্ন করার প্রয়োজন নেই।
- Callable: এটি থ্রেডে কাজের শেষে একটি ভ্যালু রিটার্ন করতে সক্ষম এবং এটি exception থ্রো করতে পারে। এটি সাধারণত asynchronous কাজের জন্য ব্যবহৃত হয়।
- Comparator: এটি দুটি অবজেক্টের তুলনা করতে ব্যবহৃত হয় এবং sorting বা ordering এর জন্য কাজ করে।
Functional Interfaces এর মাধ্যমে Java 8 থেকে ফাংশনাল প্রোগ্রামিংয়ের ধারণা বাস্তবায়িত হয়েছে এবং lambda expressions ব্যবহার করে কোড আরও সংক্ষিপ্ত ও পরিষ্কার করা সম্ভব হয়েছে।
Functional Interface হল একটি ইন্টারফেস যা শুধুমাত্র একটিমাত্র abstract method ধারণ করে। Java 8 এর পর থেকে, আপনি functional interfaces ব্যবহার করতে পারেন, যা Lambda expressions বা method references এর মাধ্যমে ফাংশনাল প্রোগ্রামিং বাস্তবায়নে সহায়ক। java.util.function প্যাকেজে বেশ কিছু বিল্ট-ইন ফাংশনাল ইন্টারফেস রয়েছে, তবে আপনি নিজের custom functional interface তৈরি করতে পারেন যা আপনার প্রয়োজন অনুযায়ী কাস্টম লজিক বাস্তবায়ন করে।
এখানে Custom Functional Interface তৈরি করার পুরো প্রক্রিয়া বিস্তারিতভাবে ব্যাখ্যা করা হয়েছে।
1. Custom Functional Interface তৈরি করা
ফাংশনাল ইন্টারফেস তৈরি করতে, @FunctionalInterface annotation ব্যবহার করা উত্তম, যদিও এটি বাধ্যতামূলক নয়। এটি শুধুমাত্র ইন্টারফেসের মধ্যে একটিমাত্র abstract method থাকতে হবে, এবং আপনি যদি দুইটি বা তার বেশি abstract method যোগ করার চেষ্টা করেন, তবে কম্পাইলার ত্রুটি দেখাবে।
Custom Functional Interface উদাহরণ:
ধরা যাক, আমরা একটি ফাংশনাল ইন্টারফেস তৈরি করতে চাই যেটি দুইটি ইন্টিজার ইনপুট গ্রহণ করবে এবং তাদের যোগফল প্রদান করবে।
@FunctionalInterface
public interface IntegerOperation {
int operate(int a, int b); // Single abstract method
// You can also have default or static methods
default int square(int a) {
return a * a;
}
}
Explanation:
- @FunctionalInterface: এটি এই ইন্টারফেসকে একটি ফাংশনাল ইন্টারফেস হিসেবে চিহ্নিত করে এবং একাধিক abstract method থাকলে কম্পাইলার ত্রুটি প্রদান করবে।
- operate: এটি আমাদের একমাত্র abstract method, যা দুটি int ইনপুট নিয়ে একটি ফলাফল প্রদান করে।
2. Custom Functional Interface এর মাধ্যমে Lambda Expression ব্যবহার করা
আপনি যখন একটি Functional Interface তৈরি করেন, তখন আপনি Lambda Expression এর মাধ্যমে সেই ইন্টারফেসের abstract method বাস্তবায়ন করতে পারেন।
Lambda Expression উদাহরণ:
public class Main {
public static void main(String[] args) {
// Creating an instance of IntegerOperation using a lambda expression
IntegerOperation add = (a, b) -> a + b;
// Calling the 'operate' method using the lambda expression
int result = add.operate(5, 3);
System.out.println("Addition result: " + result); // Output: 8
// Using default method
System.out.println("Square of 4: " + add.square(4)); // Output: 16
}
}
Explanation:
- Lambda Expression
(a, b) -> a + b: এটি IntegerOperation ইন্টারফেসের operate মেথডের বাস্তবায়ন, যেখানে দুটি ইনপুট (a এবং b) গ্রহণ করে তাদের যোগফল প্রদান করা হয়। - Default Method:
square(4)মেথডটি default হিসেবে ইন্টারফেসে প্রদান করা হয়েছিল, এবং এটি ব্যবহার করা হয়। default মেথডের মাধ্যমে ইন্টারফেসে লজিক সংযুক্ত করা সম্ভব।
3. Multiple Functional Interfaces (কমপ্লেক্স ফাংশনাল ইন্টারফেস)
একইভাবে, আপনি আরও জটিল ফাংশনাল ইন্টারফেস তৈরি করতে পারেন যেগুলিতে একাধিক abstract method থাকে, বা generic types ব্যবহার করতে পারেন।
Multiple Method Custom Functional Interface উদাহরণ:
@FunctionalInterface
public interface MathOperation<T> {
T operate(T a, T b); // Single abstract method for operation
default T add(T a, T b) {
return operate(a, b);
}
default T subtract(T a, T b) {
return operate(a, b);
}
}
Explanation:
- এখানে, MathOperation একটি generic ইন্টারফেস, যার মাধ্যমে আপনি একাধিক ধরনের ডেটা টাইপের উপর addition এবং subtraction অপারেশন করতে পারেন।
- default methods
add()এবংsubtract()ইন্টারফেসে লজিক সরবরাহ করছে, এবং operate() এর মাধ্যমে অপারেশনটি বাস্তবায়িত হচ্ছে।
Lambda Expression with Generic Interface উদাহরণ:
public class Main {
public static void main(String[] args) {
// Creating instance of MathOperation using lambda expression
MathOperation<Integer> addIntegers = (a, b) -> a + b;
MathOperation<Double> addDoubles = (a, b) -> a + b;
// Perform addition and subtraction on integers
System.out.println("Integer addition: " + addIntegers.add(5, 3)); // Output: 8
System.out.println("Integer subtraction: " + addIntegers.subtract(5, 3)); // Output: 2
// Perform addition on doubles
System.out.println("Double addition: " + addDoubles.add(2.5, 3.7)); // Output: 6.2
}
}
Explanation:
- এখানে, MathOperation এবং MathOperation টাইপের উপর অপারেশন চালানো হচ্ছে। generic ইন্টারফেসের মাধ্যমে আপনি একই লজিক ব্যবহার করতে পারেন বিভিন্ন ধরনের ডেটা টাইপে।
4. Using Multiple Custom Functional Interfaces
Java তে আপনি একাধিক ফাংশনাল ইন্টারফেসও ব্যবহার করতে পারেন, যেমন একাধিক কম্পোজিশন বা বিভিন্ন স্ট্রিম অপারেশন করতে।
Multiple Functional Interfaces Example:
@FunctionalInterface
public interface StringOperation {
String operate(String a, String b);
}
public class Main {
public static void main(String[] args) {
// Concatenation of two strings using lambda expression
StringOperation concatenate = (a, b) -> a + " " + b;
System.out.println(concatenate.operate("Hello", "World")); // Output: Hello World
}
}
Explanation:
- StringOperation ইন্টারফেসে দুটি String ইনপুট নিয়ে তাদের concatenate করে দেয়।
5. Using Built-in Functional Interfaces
Java 8-এ java.util.function প্যাকেজে অনেক বিল্ট-ইন ফাংশনাল ইন্টারফেস আছে যেমন Function, Predicate, Consumer, Supplier ইত্যাদি, যা ফাংশনাল প্রোগ্রামিং সহজ করে তোলে। আপনি আপনার কাস্টম ইন্টারফেস এবং বিল্ট-ইন ইন্টারফেস একসাথে ব্যবহার করতে পারেন।
Function Interface Example:
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
Function<Integer, Integer> multiplyByTwo = x -> x * 2;
System.out.println(multiplyByTwo.apply(5)); // Output: 10
}
}
Explanation:
- Function<Integer, Integer>: এটি একটি বিল্ট-ইন ফাংশনাল ইন্টারফেস যা একটি Integer ইনপুট গ্রহণ করে এবং একটি Integer আউটপুট প্রদান করে।
সারাংশ
Java তে Custom Functional Interface তৈরি করা খুবই সহজ এবং কার্যকরী। আপনি Lambda Expressions এবং Method References এর মাধ্যমে এই ইন্টারফেসগুলির ব্যবহার করতে পারেন এবং কার্যকারিতা বৃদ্ধি করতে পারেন। Java 8 এর পর থেকে Functional Interfaces এবং Lambda Expressions এর সাহায্যে কোড আরও সংক্ষিপ্ত এবং ক্লিন করা সম্ভব, যা ফাংশনাল প্রোগ্রামিং প্যাটার্নে কোড লেখার একটি উন্নত পদ্ধতি।
- Custom Functional Interface তৈরি করতে @FunctionalInterface annotation ব্যবহার করুন।
- Lambda Expressions এবং Method References ব্যবহার করে ইন্টারফেসের মেথড গুলি ইমপ্লিমেন্ট করুন।
- Generic Types এবং Multiple Methods ব্যবহার করে আরও শক্তিশালী কাস্টম ইন্টারফেস তৈরি করুন।
Read more