Java 8-এ Collectors একটি শক্তিশালী উপাদান হিসেবে উপস্থিত হয়েছে, যা Stream API-র সাথে কাজ করার জন্য সহজে ডেটা সংগ্রহ করতে সাহায্য করে। Java 8-এ কিছু বিল্ট-ইন Collectors যেমন Collectors.toList(), Collectors.toSet(), এবং Collectors.joining() রয়েছে, তবে আপনি নিজের Custom Collectors তৈরি করে আরও নির্দিষ্টভাবে ডেটা সংগ্রহের কাজ করতে পারেন।
Custom Collector তৈরি করা হয় Collector ইন্টারফেসের মাধ্যমে, যা মূলত তিনটি কম্পোনেন্ট দ্বারা কাজ করে:
- Supplier: একটি নতুন সংগ্রহ তৈরি করে।
- Accumulator: স্ট্রিমের প্রতিটি উপাদান সংগ্রহে যুক্ত করে।
- Combiner: মাল্টিপল উপাদানগুলিকে একত্রে যোগ করে।
এছাড়া finisher এবং characteristics ফাংশনগুলোও থাকতে পারে।
১. Custom Collector তৈরি
একটি Custom Collector তৈরি করতে আমরা Collector ইন্টারফেসের তিনটি মেথড ইমপ্লিমেন্ট করি:
- supplier() – নতুন একটি সংগ্রহ তৈরি করবে।
- accumulator() – প্রতিটি উপাদান সংগ্রহে যুক্ত করবে।
- combiner() – মাল্টিপল সংগ্রহকে একত্রিত করবে।
এছাড়া, finisher() (যদি দরকার হয়) এবং characteristics() মেথডও ইমপ্লিমেন্ট করা যেতে পারে।
উদাহরণ: Custom Collector - List of Strings Concatenation
আমরা একটি Custom Collector তৈরি করব যা স্ট্রিংগুলির একটি তালিকাকে একত্রিত করবে।
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
public class CustomCollectorExample {
public static void main(String[] args) {
List<String> strings = Arrays.asList("Java", "is", "awesome");
// Custom Collector তৈরি
Collector<String, StringBuilder, String> customCollector = Collector.of(
StringBuilder::new, // Supplier: নতুন StringBuilder তৈরি করা
StringBuilder::append, // Accumulator: StringBuilder এ স্ট্রিং অ্যাড করা
StringBuilder::append, // Combiner: দুটি StringBuilder একত্র করা
StringBuilder::toString // Finisher: StringBuilder কে স্ট্রিং-এ রূপান্তর করা
);
// Custom Collector ব্যবহার
String result = strings.stream().collect(customCollector);
System.out.println(result); // Output: Java is awesome
}
}ব্যাখ্যা:
- Supplier:
StringBuilder::new- এটি একটি নতুনStringBuilderতৈরি করবে। - Accumulator:
StringBuilder::append- এটি স্ট্রিং গুলোStringBuilderএ যুক্ত করবে। - Combiner:
StringBuilder::append- এটি দুটিStringBuilderকে একত্রিত করবে। - Finisher:
StringBuilder::toString- এটি স্ট্রিং হিসেবে রিটার্ন করবে।
২. Custom Collector - Counting Occurrences of Elements
এখন একটি কাস্টম কলেক্টর তৈরি করা হবে যা একটি তালিকাতে প্রতিটি উপাদানের উপস্থিতির সংখ্যা গননা করবে।
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
public class CustomCollectorExample {
public static void main(String[] args) {
List<String> fruits = Arrays.asList("Apple", "Banana", "Apple", "Orange", "Banana", "Apple");
// Custom Collector তৈরি
Collector<String, Map<String, Integer>, Map<String, Integer>> countCollector = Collector.of(
HashMap::new, // Supplier: একটি নতুন HashMap তৈরি করবে
(map, fruit) -> map.merge(fruit, 1, Integer::sum), // Accumulator: ফ্রুটের কাউন্ট বাড়ানো
(map1, map2) -> { // Combiner: দুটি মাপ একত্রিত করা
map1.forEach((key, value) -> map2.merge(key, value, Integer::sum));
return map2;
},
Function.identity() // Finisher: Map ফিরিয়ে দেবে
);
// Custom Collector ব্যবহার
Map<String, Integer> fruitCount = fruits.stream().collect(countCollector);
System.out.println(fruitCount); // Output: {Apple=3, Banana=2, Orange=1}
}
}ব্যাখ্যা:
- Supplier:
HashMap::new- এটি একটি নতুনHashMapতৈরি করবে যেখানে কীগুলো হবে স্ট্রিং এবং মান হবে ইন্টিজার। - Accumulator:
map.merge(fruit, 1, Integer::sum)- এটি প্রতিটি ফ্রুটের জন্য তার উপস্থিতি গননা করবে। - Combiner:
map1.forEach(...)- দুটিHashMapএকত্রিত করবে। - Finisher:
Function.identity()- এখানে কোনো পরিবর্তন নেই, শুধুMapকে ফিরিয়ে দেওয়া হচ্ছে।
৩. Custom Collector - Grouping Data
আমরা একটি কাস্টম কলেক্টর তৈরি করতে পারি যা কিছু ডেটাকে গ্রুপিং করবে। উদাহরণস্বরূপ, যদি আমরা ফ্রুটগুলিকে তাদের প্রকার (যেমন "Citrus" এবং "Non-Citrus") অনুযায়ী গ্রুপ করতে চাই, তাহলে কাস্টম গ্রুপিং কলেক্টর ব্যবহার করা যায়।
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
public class CustomCollectorExample {
public static void main(String[] args) {
List<String> fruits = Arrays.asList("Apple", "Orange", "Lemon", "Banana", "Grapefruit");
// Custom Collector তৈরি
Collector<String, Map<String, List<String>>, Map<String, List<String>>> groupCollector = Collector.of(
HashMap::new, // Supplier: একটি নতুন HashMap তৈরি করবে
(map, fruit) -> { // Accumulator: গ্রুপিং যুক্ত করা
String key = fruit.equals("Orange") || fruit.equals("Lemon") || fruit.equals("Grapefruit") ? "Citrus" : "Non-Citrus";
map.computeIfAbsent(key, k -> new ArrayList<>()).add(fruit);
},
(map1, map2) -> { // Combiner: দুটি মাপ একত্রিত করা
map1.forEach((key, value) -> map2.merge(key, value, (v1, v2) -> { v1.addAll(v2); return v1; }));
return map2;
},
Function.identity() // Finisher: ফাইনাল গ্রুপিং ফিরে দেওয়া
);
// Custom Collector ব্যবহার
Map<String, List<String>> groupedFruits = fruits.stream().collect(groupCollector);
System.out.println(groupedFruits); // Output: {Non-Citrus=[Apple, Banana], Citrus=[Orange, Lemon, Grapefruit]}
}
}ব্যাখ্যা:
- Supplier:
HashMap::new- একটি নতুনHashMapতৈরি করবে। - Accumulator:
map.computeIfAbsent()- ফ্রুটগুলি তাদের প্রকার অনুযায়ী গ্রুপ করবে। - Combiner:
map1.forEach(...)- দুটিMapএকত্রিত করবে। - Finisher:
Function.identity()- কোনো পরিবর্তন ছাড়া ফাইনাল গ্রুপিং ম্যাপ ফেরত দেবে।
৪. Collectors Supporting Characteristics
একটি কাস্টম কলেক্টর তৈরি করার সময় আপনি characteristics() মেথডও ব্যবহার করতে পারেন, যা সংগ্রহের প্রকৃতি সম্পর্কে কিছু তথ্য দেয়। সাধারণত এটি CONCURRENT, UNORDERED, এবং IDEMPOTENT থাকতে পারে।
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
public class CustomCollectorExample {
public static void main(String[] args) {
List<String> fruits = Arrays.asList("Apple", "Orange", "Banana", "Grapefruit");
// Custom Collector তৈরি
Collector<String, List<String>, List<String>> customCollector = Collector.of(
ArrayList::new,
List::add,
(list1, list2) -> { list1.addAll(list2); return list1; },
Function.identity(),
Collector.Characteristics.IDENTITY_FINISH
);
List<String> fruitList = fruits.stream().collect(customCollector);
System.out.println(fruitList); // Output: [Apple, Orange, Banana, Grapefruit]
}
}সারসংক্ষেপ
- Custom Collectors তৈরি করার জন্য
Collectorইন্টারফেস ইমপ্লিমেন্ট করতে হয়, যেখানে আপনাকে supplier(), accumulator(), এবং combiner() মেথডগুলো প্রদান করতে হয়। - আপনি finisher(), characteristics() মেথডও কাস্টমাইজ করতে পারেন।
- Custom Collectors ব্যবহার করে আপনি জটিল ডেটা সংগ্রহ এবং ম্যানিপুলেশন করতে পারেন যেমন গুণাগুণ গণনা, গ্রুপিং, কাস্টম ফরম্যাটে ডেটা একত্রিত করা ইত্যাদি।
Read more