Java 8 থেকে ফাংশনাল প্রোগ্রামিং কনসেপ্ট, যেমন Lambda Expressions, Method References, এবং Streams API, প্রবর্তিত হয়েছে। Generics এবং ফাংশনাল প্রোগ্রামিং একত্রে ব্যবহার করলে প্রোগ্রামিং আরও শক্তিশালী এবং টাইপ-সেফ হয়।
Lambda Expressions ফাংশনাল প্রোগ্রামিংয়ের একটি মূল অংশ। এটি একটি ফাংশনকে কোডের অংশ হিসেবে পাস করার সুবিধা দেয়। Generics এর মাধ্যমে Lambda Expressions টাইপ সেফটি নিশ্চিত করে।
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
Function<String, Integer> stringToLength = (String s) -> s.length();
System.out.println(stringToLength.apply("Generics and Functional Programming"));
}
}
Explanation:
Function<String, Integer>
একটি জেনেরিক ইন্টারফেস যা একটি String
ইনপুট নেয় এবং একটি Integer
রিটার্ন করে।(String s) -> s.length()
টাইপ সেফভাবে কাজ করে।Java 8-এ অনেকগুলো Functional Interface প্রবর্তিত হয়েছে, যেমন Function
, Consumer
, Supplier
, এবং Predicate
। এগুলো জেনেরিক্স ব্যবহার করে টাইপ সেফ প্রোগ্রামিং নিশ্চিত করে।
Functional Interface | Generic Declaration | Purpose |
---|---|---|
Function<T, R> | T (input), R (output) | একটি ইনপুট নিয়ে একটি আউটপুট প্রদান করে। |
Consumer<T> | T (input) | একটি ইনপুট গ্রহণ করে, কিছু কাজ করে, কিন্তু কিছু রিটার্ন করে না। |
Supplier<T> | T (output) | কোনো ইনপুট নেয় না, একটি আউটপুট প্রদান করে। |
Predicate<T> | T (input) | একটি ইনপুট গ্রহণ করে, একটি Boolean রিটার্ন করে। |
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
Function<Integer, String> intToString = (Integer i) -> "Number: " + i;
System.out.println(intToString.apply(10));
}
}
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
Consumer<String> printConsumer = (String s) -> System.out.println(s);
printConsumer.accept("Hello, Generics and Functional Programming!");
}
}
import java.util.function.Supplier;
public class Main {
public static void main(String[] args) {
Supplier<Double> randomSupplier = () -> Math.random();
System.out.println("Random number: " + randomSupplier.get());
}
}
import java.util.function.Predicate;
public class Main {
public static void main(String[] args) {
Predicate<Integer> isEven = (Integer i) -> i % 2 == 0;
System.out.println("Is 10 even? " + isEven.test(10));
}
}
Streams API জাভার ডেটা প্রসেসিংয়ের জন্য একটি শক্তিশালী টুল, এবং এটি Generics এর উপর ভিত্তি করে তৈরি। এটি টাইপ সেফ এবং Declarative Programming কে সমর্থন করে।
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("John", "Alice", "Bob", "Catherine");
names.stream()
.filter(name -> name.startsWith("C"))
.map(String::toUpperCase)
.forEach(System.out::println);
}
}
Explanation:
filter
একটি Predicate
নেয়।map
একটি Function
নেয়।forEach
একটি Consumer
নেয়।import java.util.Arrays;
import java.util.List;
class Box<T> {
private T value;
public Box(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
public class Main {
public static void main(String[] args) {
List<Box<String>> boxes = Arrays.asList(
new Box<>("Apple"),
new Box<>("Banana"),
new Box<>("Cherry")
);
boxes.stream()
.map(Box::getValue)
.map(String::toUpperCase)
.forEach(System.out::println);
}
}
আউটপুট:
APPLE
BANANA
CHERRY
Method References Lambda Expressions এর একটি সংক্ষিপ্ত রূপ। এটি Generics এর সাথে টাইপ সেফভাবে কাজ করে।
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("John", "Alice", "Bob");
// Method Reference: String::toUpperCase
names.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
}
}
Java 8+ এর ফাংশনাল প্রোগ্রামিং এবং Generics একত্রে ব্যবহার টাইপ সেফ, সংক্ষিপ্ত, এবং কার্যকর প্রোগ্রাম তৈরি করতে সাহায্য করে। Lambda Expressions, Method References, এবং Streams API জেনেরিক্সের ক্ষমতা বৃদ্ধি করেছে। তবে, এই সুবিধাগুলো ব্যবহারের সময় কোডের জটিলতা এবং Type Erasure সম্পর্কিত সীমাবদ্ধতার ব্যাপারে সচেতন থাকতে হবে।
Java 8 এ Functional Programming এর সংযোজন জাভার প্রোগ্রামিং স্টাইলকে একটি নতুন মাত্রা দিয়েছে। Lambda Expressions, Streams API, এবং Functional Interfaces এর মাধ্যমে কোড আরও সংক্ষিপ্ত, রিডেবল এবং কার্যকর হয়েছে। জেনেরিক্স এই নতুন ফিচারগুলির সাথে সামঞ্জস্য রেখে টাইপ সেফটি এবং ফ্লেক্সিবিলিটি প্রদান করে। এখানে Java 8 এবং তারপরে Functional Programming এর বিভিন্ন দিক এবং জেনেরিক্সের ভূমিকা আলোচনা করা হলো।
Lambda Expressions মূলত একটি Functional Interface (যার মধ্যে একটি মাত্র অ্যাবস্ট্রাক্ট মেথড থাকে) ব্যবহার করে কাজ করে। Lambda Expressions জেনেরিক্সের সাথে মিলিয়ে ব্যবহার করলে টাইপ সেফ কোড লেখা যায়।
import java.util.function.Function;
public class GenericLambdaExample {
public static void main(String[] args) {
// Generic Lambda
Function<String, Integer> stringToLength = str -> str.length();
System.out.println("Length of 'Java': " + stringToLength.apply("Java"));
Function<Integer, String> intToString = num -> "Number: " + num;
System.out.println(intToString.apply(42));
}
}
Length of 'Java': 4
Number: 42
Java 8 এ অনেক বিল্ট-ইন Functional Interfaces এসেছে, যেমন:
import java.util.function.Predicate;
public class GenericPredicateExample {
public static void main(String[] args) {
Predicate<String> isNotEmpty = str -> str != null && !str.isEmpty();
System.out.println(isNotEmpty.test("Hello")); // true
System.out.println(isNotEmpty.test("")); // false
}
}
Java 8 এর Streams API জেনেরিক টাইপ ব্যবহার করে Collections এর উপর অপারেশন পরিচালনা করে। এটি টাইপ সেফ এবং সহজে ব্যবহারযোগ্য।
import java.util.Arrays;
import java.util.List;
public class StreamGenericExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
// Filter and Map using Generics
names.stream()
.filter(name -> name.startsWith("A")) // Predicate<String>
.map(String::toUpperCase) // Function<String, String>
.forEach(System.out::println); // Consumer<String>
}
}
ALICE
Java 8 এ Optional<T>
এসেছে NullPointerException এড়ানোর জন্য। এটি একটি জেনেরিক ক্লাস এবং ফাংশনাল প্রোগ্রামিং স্টাইলে ডেটা ম্যানিপুলেশন করতে ব্যবহৃত হয়।
import java.util.Optional;
public class OptionalGenericExample {
public static void main(String[] args) {
Optional<String> optionalName = Optional.of("Java Generics");
optionalName.ifPresent(System.out::println); // Prints the value if present
}
}
Java 8 এর আগে যদি জেনেরিক ফাংশনাল ইন্টারফেস তৈরি করতে হতো, তবে এটি ম্যানুয়ালি করতে হতো। তবে, Functional Interfaces এর সংযোজনের পরে এটি আরও সহজ হয়েছে।
@FunctionalInterface
interface GenericFunction<T, R> {
R apply(T t);
}
public class CustomGenericFunction {
public static void main(String[] args) {
GenericFunction<String, Integer> stringToLength = str -> str.length();
System.out.println("Length: " + stringToLength.apply("Functional Generics"));
}
}
Java 8 এর parallel streams কোডে সহজে কনকারেন্ট প্রসেসিং চালানোর সুযোগ দেয়, এবং এটি Generics এর সাহায্যে টাইপ সেফ এবং সহজ করে।
import java.util.Arrays;
import java.util.List;
public class ParallelStreamExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.parallelStream()
.map(num -> num * num) // Function<Integer, Integer>
.forEach(System.out::println);
}
}
Java 8 এর Collectors API ডেটা সংগ্রহ করতে ব্যবহৃত হয় এবং এটি Generics এর সাহায্যে টাইপ সেফ ভাবে কাজ করে।
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class CollectorsExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
// Collect names starting with 'C'
List<String> result = names.stream()
.filter(name -> name.startsWith("C")) // Predicate<String>
.collect(Collectors.toList());
System.out.println(result);
}
}
[Charlie]
Java 8 এবং তারপরে Functional Programming এবং Generics এর সংমিশ্রণ জাভার প্রোগ্রামিং শৈলীকে আরও শক্তিশালী করেছে। নিচে এর সুবিধাগুলো উল্লেখ করা হলো:
সঠিকভাবে Generics এবং Functional Programming ব্যবহার করলে টাইপ সেফটি নিশ্চিত হয় এবং কোড আরও রিডেবল, সংক্ষিপ্ত এবং কার্যকর হয়।
জাভা ৮ থেকে Lambda Expressions এবং Generics একসঙ্গে ব্যবহার করে আরও কার্যকর এবং সংক্ষিপ্ত কোড লেখা সম্ভব হয়েছে। Lambda Expressions মূলত ফাংশনাল প্রোগ্রামিং ধারণা নিয়ে এসেছে, যা Functional Interfaces এর মাধ্যমে কাজ করে। জেনেরিক্সের সাথে Lambda ব্যবহার করার ফলে টাইপ সেফ এবং পুনঃব্যবহারযোগ্য কোড তৈরি করা যায়।
Syntax:
(parameters) -> expression
Lambda এবং জেনেরিক্স ব্যবহার করে তালিকা (List) সাজানো সহজ হয়।
import java.util.*;
public class LambdaWithGenerics {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// Using Lambda Expression for Comparator
names.sort((s1, s2) -> s1.compareTo(s2));
System.out.println(names); // [Alice, Bob, Charlie]
}
}
Lambda ব্যবহার করে জেনেরিক মেথডকে আরও কার্যকর করা যায়।
import java.util.function.Function;
public class GenericLambdaExample {
public static <T, R> R applyFunction(T input, Function<T, R> function) {
return function.apply(input);
}
public static void main(String[] args) {
String result = applyFunction(5, x -> "Number: " + (x * 2));
System.out.println(result); // Number: 10
}
}
Predicate একটি ফাংশনাল ইন্টারফেস যা একটি ইনপুট নিয়ে বুলিয়ান আউটপুট দেয়। এটি ফিল্টার করার জন্য সাধারণত ব্যবহৃত হয়।
import java.util.*;
import java.util.function.Predicate;
public class GenericPredicateExample {
public static <T> List<T> filterList(List<T> list, Predicate<T> predicate) {
List<T> result = new ArrayList<>();
for (T item : list) {
if (predicate.test(item)) {
result.add(item);
}
}
return result;
}
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// Filter even numbers
List<Integer> evens = filterList(numbers, x -> x % 2 == 0);
System.out.println(evens); // [2, 4]
}
}
Consumer ফাংশনাল ইন্টারফেস একটি ইনপুট গ্রহণ করে এবং কোনো রিটার্ন না দিয়ে কাজ সম্পন্ন করে।
import java.util.*;
import java.util.function.Consumer;
public class GenericConsumerExample {
public static <T> void processItems(List<T> list, Consumer<T> consumer) {
for (T item : list) {
consumer.accept(item);
}
}
public static void main(String[] args) {
List<String> items = Arrays.asList("Java", "Generics", "Lambda");
processItems(items, item -> System.out.println(item.toUpperCase()));
}
}
JAVA
GENERICS
LAMBDA
Supplier ফাংশনাল ইন্টারফেস কোনো ইনপুট নেয় না এবং একটি আউটপুট প্রদান করে।
import java.util.function.Supplier;
public class GenericSupplierExample {
public static <T> T provideItem(Supplier<T> supplier) {
return supplier.get();
}
public static void main(String[] args) {
String message = provideItem(() -> "Hello, Lambda and Generics!");
System.out.println(message);
}
}
?
) ব্যবহার Lambda এর কার্যকারিতা সীমাবদ্ধ করতে পারে।Lambda Expressions এবং Generics একত্রে ব্যবহারে জাভা প্রোগ্রামিং আরও সংক্ষিপ্ত, ফ্লেক্সিবল এবং কার্যকর হয়েছে। এটি বড় স্কেল প্রজেক্টে টাইপ সেফটি নিশ্চিত করার পাশাপাশি কার্যকারিতা বাড়িয়ে দেয়। সঠিকভাবে Lambda এবং Generics ব্যবহার করে কোড সহজবোধ্য এবং রিডেবল রাখা সম্ভব।
জাভার Streams API এবং Generics একসাথে ব্যবহার করে ডেটা প্রসেসিং আরও শক্তিশালী, ফ্লেক্সিবল এবং টাইপ-সেইফ করা যায়। Generics Streams API-তে টাইপের নিরাপত্তা নিশ্চিত করে এবং ডেটা প্রসেসিংয়ে কম্পাইল-টাইম চেকিং নিশ্চিত করে।
List<T>
, Set<T>
) থেকে স্ট্রিম তৈরি করতে ব্যবহৃত হয়।import java.util.Arrays;
import java.util.List;
public class GenericStreamExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
// Stream তৈরি এবং প্রসেসিং
names.stream()
.filter(name -> name.startsWith("A"))
.forEach(System.out::println); // Output: Alice
}
}
import java.util.List;
import java.util.stream.Collectors;
public class GenericStreamMethod {
// জেনেরিক মেথড
public static <T> List<T> filterItems(List<T> items, java.util.function.Predicate<T> predicate) {
return items.stream()
.filter(predicate)
.collect(Collectors.toList());
}
public static void main(String[] args) {
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6);
// Even সংখ্যা ফিল্টার করা
List<Integer> evenNumbers = filterItems(numbers, num -> num % 2 == 0);
System.out.println("Even Numbers: " + evenNumbers); // Output: [2, 4, 6]
List<String> words = List.of("apple", "banana", "cherry", "date");
List<String> shortWords = filterItems(words, word -> word.length() <= 5);
System.out.println("Short Words: " + shortWords); // Output: [apple, banana, cherry, date]
}
}
import java.util.Arrays;
import java.util.List;
public class GenericStreamMapReduce {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// Map এবং Reduce অপারেশন
int sumOfSquares = numbers.stream()
.map(num -> num * num) // প্রতিটি সংখ্যার স্কোয়ার
.reduce(0, Integer::sum); // সবগুলোর যোগফল
System.out.println("Sum of Squares: " + sumOfSquares); // Output: 55
}
}
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
class Product {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
@Override
public String toString() {
return name + ": $" + price;
}
}
public class GenericStreamWithCustomClass {
public static void main(String[] args) {
List<Product> products = Arrays.asList(
new Product("Laptop", 800.00),
new Product("Phone", 500.00),
new Product("Tablet", 300.00),
new Product("Headphones", 50.00)
);
// ফিল্টার করে প্রোডাক্টের নামের তালিকা তৈরি
List<String> expensiveProductNames = products.stream()
.filter(product -> product.getPrice() > 300.00)
.map(Product::getName)
.collect(Collectors.toList());
System.out.println("Expensive Products: " + expensiveProductNames);
// Output: [Laptop, Phone]
}
}
import java.util.Arrays;
import java.util.List;
public class ParallelStreamExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// Parallel Stream ব্যবহার
int sum = numbers.parallelStream()
.filter(num -> num % 2 == 0) // Even সংখ্যা ফিল্টার করা
.mapToInt(num -> num * 2) // প্রতিটি সংখ্যা দ্বিগুণ করা
.sum();
System.out.println("Sum of doubled even numbers: " + sum); // Output: 60
}
}
Generics এবং Streams API একত্রে ব্যবহার করলে জাভার ডেটা প্রসেসিং আরও কার্যকর ও টাইপ-সেইফ হয়। Collections Framework থেকে সহজে স্ট্রিম তৈরি, জেনেরিক মেথডের মাধ্যমে ফ্লেক্সিবল পাইপলাইন তৈরি, এবং জটিল ডেটা প্রক্রিয়া সহজতর করার জন্য Generics অত্যন্ত কার্যকর। সঠিকভাবে Generics এবং Streams API ব্যবহার করলে প্রোগ্রামিং আরও কার্যকর ও রিইউজেবল হয়ে ওঠে।
Functional Interfaces এবং Generics একত্রে ব্যবহার করে কোডের ফ্লেক্সিবিলিটি এবং পুনঃব্যবহারযোগ্যতা বাড়ানো যায়। Functional Interfaces হল এক ধরনের ইন্টারফেস, যেখানে শুধুমাত্র একটি অ্যাবস্ট্রাক্ট মেথড থাকে। Generics এর মাধ্যমে Functional Interfaces টাইপ-অ্যাগনস্টিক করা যায়, যা কোডে টাইপ সেফটি এবং রিডেবিলিটি নিশ্চিত করে।
Common Functional Interfaces (java.util.function):
Function<T, R>
: একটি ইনপুট নিয়ে একটি আউটপুট প্রদান করে।Predicate<T>
: একটি শর্ত যাচাই করে boolean
আউটপুট প্রদান করে।Consumer<T>
: ইনপুট গ্রহণ করে কিন্তু কিছু রিটার্ন করে না।Supplier<T>
: কোনো ইনপুট ছাড়া একটি আউটপুট প্রদান করে।BiFunction<T, U, R>
: দুটি ইনপুট নিয়ে একটি আউটপুট প্রদান করে।@FunctionalInterface
interface Transformer<T, R> {
R transform(T input);
}
public class Main {
public static void main(String[] args) {
// String to Integer Transformer
Transformer<String, Integer> stringToInteger = Integer::parseInt;
System.out.println("String to Integer: " + stringToInteger.transform("123"));
// Integer to Double Transformer
Transformer<Integer, Double> intToDouble = input -> input * 2.5;
System.out.println("Integer to Double: " + intToDouble.transform(10));
}
}
String to Integer: 123
Integer to Double: 25.0
উপকারিতা:
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
// Function to calculate square
Function<Integer, Integer> square = x -> x * x;
System.out.println("Square of 5: " + square.apply(5));
// Function to convert String to Uppercase
Function<String, String> toUpperCase = String::toUpperCase;
System.out.println("Uppercase: " + toUpperCase.apply("hello"));
}
}
Square of 5: 25
Uppercase: HELLO
উপকারিতা:
import java.util.function.Predicate;
public class Main {
public static void main(String[] args) {
// Predicate to check if a number is even
Predicate<Integer> isEven = x -> x % 2 == 0;
System.out.println("Is 4 even? " + isEven.test(4));
System.out.println("Is 7 even? " + isEven.test(7));
}
}
Is 4 even? true
Is 7 even? false
উপকারিতা:
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
// Consumer to print a value
Consumer<String> printer = System.out::println;
printer.accept("Hello, World!");
}
}
Hello, World!
উপকারিতা:
import java.util.function.Supplier;
public class Main {
public static void main(String[] args) {
// Supplier to provide a default value
Supplier<String> defaultMessage = () -> "Default Message";
System.out.println(defaultMessage.get());
}
}
Default Message
উপকারিতা:
import java.util.function.Function;
import java.util.function.Predicate;
public class Main {
public static void main(String[] args) {
// Predicate to check if a number is positive
Predicate<Integer> isPositive = x -> x > 0;
// Function to calculate factorial
Function<Integer, Integer> factorial = x -> {
int result = 1;
for (int i = 1; i <= x; i++) {
result *= i;
}
return result;
};
int number = 5;
if (isPositive.test(number)) {
System.out.println("Factorial of " + number + ": " + factorial.apply(number));
} else {
System.out.println("Number must be positive!");
}
}
}
Factorial of 5: 120
উপকারিতা:
Generics এবং Functional Interfaces এর সমন্বয় বড় স্কেলের জাভা প্রজেক্টে টাইপ-সেইফ, পুনঃব্যবহারযোগ্য, এবং মেইনটেইনেবল কোড তৈরি করতে সহায়ক। এটি প্রোগ্রামের মডুলারিটি বাড়ায় এবং জাভার Functional Programming ক্ষমতাকে আরও কার্যকর করে।
Read more