Java 8-এ Streams API এবং Functional Programming (ফাংশনাল প্রোগ্রামিং) ধারণা একত্রিত হয়ে Java প্রোগ্রামিং ভাষাকে আরও শক্তিশালী, কার্যকরী এবং পরিচ্ছন্ন করে তুলেছে। Streams API-এর মাধ্যমে Java ডেভেলপাররা ফাংশনাল প্রোগ্রামিং কৌশল ব্যবহার করে ডেটার উপর ফাংশনাল অপারেশন সঞ্চালন করতে পারেন, যেমন ফিল্টারিং, ম্যাপিং, ফোল্ডিং, রিডুসিং ইত্যাদি। এটি ডেটা প্রক্রিয়াকরণে আরও পরিষ্কার, ছোট এবং কার্যকরী কোড লেখার সুযোগ দেয়।
১. Functional Programming (ফাংশনাল প্রোগ্রামিং)
Functional Programming একটি প্রোগ্রামিং প্যারাডাইম যেখানে ফাংশনগুলিকে প্রথম শ্রেণির নাগরিক হিসেবে দেখা হয় এবং তা অন্যান্য ফাংশন হিসাবে ব্যবহার করা যায়। এটি mutable state এবং side effects কমানোর চেষ্টা করে, যার ফলে কোড আরও পাঠযোগ্য এবং নির্ভরযোগ্য হয়।
ফাংশনাল প্রোগ্রামিং-এর মূল বৈশিষ্ট্য:
- Immutable state: পরিবর্তনযোগ্য অবস্থা এড়ানো হয়।
- Higher-order functions: ফাংশনগুলোকে অন্যান্য ফাংশন হিসেবে ব্যবহার করা যায়।
- No side-effects: ফাংশনগুলো বাহ্যিক অবস্থা পরিবর্তন করে না।
- Function composition: একাধিক ফাংশনকে একত্রিত করে নতুন ফাংশন তৈরি করা হয়।
২. Streams API
Java 8-এ Streams API নতুন একটি ফিচার, যা ডেটা সংগ্রহের (Collections) উপর ফাংশনাল অপারেশন পরিচালনার জন্য ব্যবহৃত হয়। এটি একাধিক ডেটা অপারেশন সঞ্চালন করে, যেমন ফিল্টার, ম্যাপ, সোর্ট, রিডিউস, ইত্যাদি।
Streams হল ডেটার একটি "ধারা" (stream) যা একটি এক্সিকিউটেবল অপারেশন একে একে সঞ্চালন করে। Streams API লেজি (lazy) অপারেশনস সমর্থন করে, যা অর্থাৎ অপারেশনগুলো তখনই সম্পাদিত হয় যখন তারা ব্যবহার করা হয়।
৩. Streams API এর প্রধান অপারেশনগুলো
১. Filter Operation
filter() অপারেশনটি একটি প্রেডিকেট ফাংশন নেয় এবং একটি স্ট্রিমের প্রতিটি উপাদান পরীক্ষা করে। এটি শুধুমাত্র সেই উপাদানগুলোকে রাখে যা প্রেডিকেট শর্ত মেনে চলে।
উদাহরণ:
import java.util.*;
import java.util.stream.*;
public class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("John", "Jane", "Mike", "Mia");
// ফিল্টার অপারেশন
names.stream()
.filter(name -> name.startsWith("J"))
.forEach(System.out::println); // John, Jane
}
}এখানে, filter() অপারেশনটি startsWith("J") শর্ত অনুসারে তালিকার নামগুলোকে ফিল্টার করছে।
২. Map Operation
map() অপারেশনটি একটি ফাংশন নেয় যা প্রতিটি উপাদানকে পরিবর্তন করে এবং একটি নতুন স্ট্রিম রিটার্ন করে।
উদাহরণ:
import java.util.*;
import java.util.stream.*;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// ম্যাপ অপারেশন
numbers.stream()
.map(num -> num * num) // প্রতিটি সংখ্যা বর্গফল
.forEach(System.out::println); // 1, 4, 9, 16, 25
}
}এখানে, map() অপারেশনটি প্রতিটি সংখ্যার বর্গফল তৈরি করছে।
৩. Reduce Operation
reduce() অপারেশনটি দুটি উপাদানকে একত্রিত করে একটি ফলস্বরূপ তৈরি করে, সাধারণত একটি অ্যাগ্রিগেট ফাংশন। এটি স্ট্রিমের সব উপাদান একত্রিত করার জন্য ব্যবহার করা হয়।
উদাহরণ:
import java.util.*;
import java.util.stream.*;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// রিডিউস অপারেশন
int sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
System.out.println("Sum: " + sum); // 15
}
}এখানে, reduce() অপারেশনটি সব সংখ্যার যোগফল বের করছে।
৪. ForEach Operation
forEach() অপারেশনটি একটি Consumer ফাংশন গ্রহণ করে এবং প্রতিটি উপাদানকে প্রসেস করে। এটি মূলত ডেটা প্রক্রিয়াকরণের জন্য ব্যবহার করা হয়।
উদাহরণ:
import java.util.*;
import java.util.stream.*;
public class Main {
public static void main(String[] args) {
List<String> names = Arrays.asList("John", "Jane", "Mike", "Mia");
// ফোরএচ অপারেশন
names.stream()
.forEach(name -> System.out.println(name));
}
}এখানে, forEach() অপারেশনটি প্রতিটি নামকে প্রিন্ট করছে।
৪. Functional Programming এর সাথে Streams API এর সংযোগ
Java 8 এর স্ট্রিম API এবং ফাংশনাল প্রোগ্রামিং ধারণা একে অপরের সাথে যুক্ত হয়ে Java ডেভেলপারদের জন্য শক্তিশালী, পরিষ্কার এবং কার্যকরী কোড লেখার সুযোগ সৃষ্টি করেছে। ফাংশনাল প্রোগ্রামিং স্টাইলের মতই স্ট্রিম API অপারেশনগুলো লেজি এবং চেইনেবল (chained) হয়, অর্থাৎ একাধিক অপারেশন একে অপরের সাথে যুক্ত করা যায়।
এছাড়াও, Streams API-এর অপারেশনগুলো immutable থাকে, কারণ একে একে নতুন স্ট্রিম তৈরি হয়, পুরনো স্ট্রিমে কোনো পরিবর্তন ঘটে না।
ফাংশনাল প্রোগ্রামিং-এর মূল বৈশিষ্ট্যগুলোর সাথে Streams API এর সম্পর্ক:
- Higher-Order Functions:
map(),filter(),reduce()ইত্যাদি ফাংশনাল অপারেশনগুলো ফাংশনাল প্রোগ্রামিং এর মূল বৈশিষ্ট্য। - Immutability: Streams অপারেশনগুলোর ফলে নতুন স্ট্রিম তৈরি হয়, পুরনো স্ট্রিমে কোনো পরিবর্তন হয় না।
- No Side Effects: Streams API ব্যবহার করার সময় অপারেশনগুলো মূল ডেটাকে পরিবর্তন করে না, বরং নতুন ডেটা তৈরি করে।
সারসংক্ষেপ
Java 8 এর Streams API এবং Functional Programming একত্রে ডেটা প্রক্রিয়াকরণকে আরও শক্তিশালী, সহজ এবং কার্যকরী করে তোলে। Streams API ব্যবহার করে আপনি ডেটা সংগ্রহের উপর map, filter, reduce এবং অন্যান্য ফাংশনাল অপারেশন চালাতে পারেন। এই অপারেশনগুলো ফাংশনাল প্রোগ্রামিং ধারণার সাথে মিল রেখে Java কোডকে আরও পরিষ্কার এবং কার্যকরী করে তোলে।
Read more