Stream Chaining এবং Filter Streams

জাভা টাপল (Java Tuples) - Java Technologies

420

Java 8 এ Stream API যোগ করা হয়েছিল, যা ডেটা প্রোসেসিং কে আরও সহজ, কার্যকর এবং রিডেবল করে। Stream Chaining এবং Filter Streams দুটি গুরুত্বপূর্ণ ধারণা যা Streams এর মাধ্যমে ডেটা প্রোসেসিং আরও শক্তিশালী এবং সুসংগঠিত করতে সাহায্য করে।


Stream Chaining

Stream Chaining হল একটি প্রক্রিয়া যেখানে একাধিক স্ট্রিম অপারেশন একত্রে ব্যবহার করা হয়, যাতে একটি স্ট্রিম থেকে অন্য স্ট্রিমে ডেটা প্রক্রিয়া করা যায়। স্ট্রিম চেনিংয়ের মাধ্যমে আপনি multiple operations (যেমন, filter(), map(), reduce() ইত্যাদি) একে অপরের সাথে একত্রে সংযুক্ত করতে পারেন।

Stream চেনিং এর প্রধান সুবিধা হল এটি নির্দিষ্ট কাজের জন্য সিকোয়েন্স চালায় এবং এটি Lazy Evaluation এর ধারণা অনুসরণ করে, যার ফলে অপারেশনগুলো শুধুমাত্র যখন প্রয়োজন তখনই কার্যকর হয়।

Stream Chaining এর উদাহরণ:

import java.util.Arrays;
import java.util.List;

public class StreamChainingExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Edward", "Frank");

        // Stream Chaining - filter, map, and collect in one chain
        names.stream()
            .filter(name -> name.startsWith("A"))   // filter names that start with 'A'
            .map(String::toUpperCase)                // convert them to uppercase
            .forEach(System.out::println);           // print each name

        // Output: 
        // ALICE
    }
}

Explanation:

  • filter() প্রথমে নামগুলোকে ফিল্টার করে যেগুলি "A" দিয়ে শুরু হয়।
  • map() সেই নামগুলোকে বড় হাতের অক্ষরে রূপান্তরিত করে।
  • forEach() তারপর ঐ নামগুলো কনসোলে প্রিন্ট করে।

এখানে, stream chaining প্রক্রিয়াটিতে ফিল্টারিং এবং রূপান্তরের অপারেশন একত্রে করা হয়েছে।


Filter Streams

Filter Streams হল স্ট্রিমে একটি নির্দিষ্ট শর্তের উপর ভিত্তি করে ডেটা ফিল্টার করার প্রক্রিয়াfilter() মেথডটি স্ট্রিমের ডেটার উপর একটি প্রেডিকেট ফাংশন প্রয়োগ করে, যা একে একে কেবলমাত্র সেই আইটেমগুলোকে রাখে যেগুলি শর্ত পূর্ণ করে।

filter() মেথডটি Stream-এর একটি অত্যন্ত গুরুত্বপূর্ণ অপারেশন যা আপনাকে ডেটাকে প্রক্রিয়া করার আগে একটি নির্দিষ্ট শর্ত অনুযায়ী ফিল্টার করার সুবিধা দেয়।

Filter Streams এর উদাহরণ:

import java.util.Arrays;
import java.util.List;

public class FilterStreamsExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // Filter Stream - filtering even numbers
        numbers.stream()
            .filter(number -> number % 2 == 0)  // Only even numbers
            .forEach(System.out::println);       // print each even number

        // Output:
        // 2
        // 4
        // 6
        // 8
        // 10
    }
}

Explanation:

  • filter(number -> number % 2 == 0) এখানে প্রেডিকেট ফাংশনটি ব্যবহার করা হয়েছে, যা শুধুমাত্র even numbers কে নির্বাচন করবে।
  • forEach(System.out::println) সমস্ত ফিল্টার করা ডেটা কনসোলে প্রিন্ট করবে।

এটি স্ট্রিমের মধ্যে একটি শর্তের ভিত্তিতে ফিল্টারিং করার একটি সহজ এবং কার্যকর উপায়।


Stream Chaining এবং Filter Streams এর উন্নত উদাহরণ

একটি উন্নত উদাহরণ দেখানো যাক, যেখানে আমরা Stream Chaining এবং Filter Streams দুইটি ধারণাকেই একত্রে ব্যবহার করব।

কোড উদাহরণ:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamChainingAndFilterExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "Edward", "Frank");

        // Stream Chaining and Filter - First filter names starting with "A", then convert to uppercase, then collect to list
        List<String> result = names.stream()
            .filter(name -> name.startsWith("A"))           // Filter names that start with 'A'
            .map(String::toUpperCase)                       // Convert them to uppercase
            .collect(Collectors.toList());                  // Collect the result into a list

        System.out.println(result);  // Output: [ALICE]
    }
}

Explanation:

  • Stream Chaining ব্যবহার করে এখানে filter(), map(), এবং collect() অপারেশন একত্রে ব্যবহার করা হয়েছে।
  • প্রথমে, filter() নামগুলিকে "A" দিয়ে শুরু হওয়া নামগুলো ফিল্টার করেছে।
  • তারপর map() অপারেশন তাদেরকে uppercase তে রূপান্তরিত করেছে।
  • সবশেষে, collect() মেথডটি ফিল্টার করা এবং রূপান্তরিত নামগুলিকে একটি List এ জমা করেছে।

এই উদাহরণে স্ট্রিম চেনিং এবং ফিল্টার স্ট্রিমের একত্রিত ব্যবহারে কার্যকর ডেটা প্রোসেসিং দেখানো হয়েছে।


Filter Streams এবং Stream Chaining এর সুবিধা

  1. Readable Code: একাধিক স্ট্রিম অপারেশন একত্রে চেইন করার মাধ্যমে কোড সহজ এবং পরিষ্কার হয়।
  2. Lazy Evaluation: স্ট্রিম অপারেশনগুলো Lazy (অলস)ভাবে সম্পাদিত হয়, অর্থাৎ তারা শুধুমাত্র তখনই কার্যকর হয় যখন আপনি স্ট্রিমকে finalize করেন (যেমন collect() বা forEach() মেথড দ্বারা)।
  3. Declarative Style: স্ট্রিম API ডেটা প্রোসেসিংয়ের জন্য একটি declarative approach প্রদান করে, যার ফলে কোডের ফ্লো আরও স্পষ্ট ও সোজা হয়।
  4. Functional Programming: স্ট্রিম API ফাংশনাল প্রোগ্রামিং ধারণাগুলোর (যেমন map(), filter(), reduce()) ব্যবহারকে সমর্থন করে।

  • Stream Chaining এবং Filter Streams হল Java Stream API-র অত্যন্ত শক্তিশালী বৈশিষ্ট্য, যা ডেটা প্রোসেসিং আরও কার্যকর এবং সুসংগঠিত করতে সহায়ক।
  • Stream Chaining দ্বারা একাধিক স্ট্রিম অপারেশনকে একত্রে চেইন করে কমপ্লেক্স ডেটা প্রোসেসিং করা সম্ভব।
  • Filter Streams ডেটার মধ্যে একটি শর্তের ভিত্তিতে ফিল্টারিং করার সুবিধা প্রদান করে।

এগুলোর সমন্বয়ে ডেটা প্রোসেসিং আরও দ্রুত, পাঠযোগ্য এবং কার্যকর হয়।

Content added By

Stream Chaining একটি শক্তিশালী কৌশল যা Java Streams API-তে ব্যবহৃত হয়, যেখানে একাধিক স্ট্রিম অপারেশন একের পর এক চেইন করে একাধিক ধাপে ডেটা প্রক্রিয়া করা হয়। এতে করে ডেটা প্রক্রিয়া এবং রূপান্তর সহজ এবং কার্যকরী হয়। স্ট্রিম চেইনিং সাধারণত Functional Programming-এর মূল ধারণা অনুযায়ী কাজ করে, যেখানে আপনি ইনপুট ডেটা উপর একাধিক পরিবর্তনশীল অপারেশন প্রয়োগ করতে পারেন এবং একাধিক স্টেপে এটি রূপান্তরিত করতে পারেন।

Java 8 থেকে Stream API চালু হওয়ার পর স্ট্রিম চেইনিং একেবারে জনপ্রিয় হয়ে উঠেছে, কারণ এটি ডেটা প্রসেসিং সহজ এবং কার্যকরী করে তোলে।


Stream Chaining এর ধারণা

Stream Chaining হলো স্ট্রিম অপারেশনগুলিকে একের পর এক পরপর প্রয়োগ করা। যখন আপনি স্ট্রিমে একাধিক অপারেশন একসাথে কল করেন, তখন প্রতিটি অপারেশন একটি নতুন স্ট্রিম রিটার্ন করে এবং ডেটা ধারাবাহিকভাবে প্রক্রিয়া হয়।

এটি মূলত method chaining ধারণার উপর ভিত্তি করে কাজ করে, যেখানে একাধিক মেথড একসাথে কল করা হয়।

Stream Chaining এর সুবিধা:

  1. Code Readability: কোড আরও পরিষ্কার এবং সংক্ষিপ্ত হয়।
  2. Declarative Approach: আপনি কী করছেন, তা স্পষ্টভাবে বলতে পারবেন (যেমন "ফিল্টার করো", "ম্যাপ করো", "সর্বোচ্চ মান বের করো", ইত্যাদি)।
  3. Performance Improvement: স্ট্রিম অপারেশনগুলি প্যারালাল প্রসেসিংয়ের জন্য ব্যবহৃত হতে পারে, যা কার্যকারিতা বাড়াতে সাহায্য করে।
  4. Functional Approach: ফাংশনাল প্রোগ্রামিং ধারণার মধ্যে স্ট্রিম চেইনিং চলে, যা মেমরি ব্যবস্থাপনা এবং ডেটা ম্যানিপুলেশন সহজ করে।

Stream Chaining এর প্রয়োজনীয়তা

  1. ডেটা ফিল্টারিং ও প্রক্রিয়া করা:
    • একাধিক স্ট্রিম অপারেশন একত্রে প্রয়োগ করতে হলে স্ট্রিম চেইনিং ব্যবহৃত হয়। উদাহরণস্বরূপ, একটি তালিকা থেকে সমস্ত সংখ্যার ফিল্টারিং এবং তাদের দ্বিগুণ করা সহজে করা যায়।
  2. Declarative Style Programming:
    • চেইনিং স্টাইল ব্যবহার করে কোড লেখার সময়, আপনি ডেটা প্রক্রিয়া করার স্টেপগুলিকে একে অপরের সাথে সংযুক্ত করতে পারেন এবং প্রতিটি স্টেপ কী করছে তা স্পষ্টভাবে নির্ধারণ করতে পারেন।
  3. Memory Efficiency:
    • স্ট্রিম অপারেশনগুলি লেজি ইভালুয়েশন ভিত্তিক হওয়ায়, তারা শুধুমাত্র প্রয়োজনীয় সময়েই ডেটা প্রক্রিয়া করে, যা মেমরি ব্যবস্থাপনা আরও দক্ষ করে।
  4. Parallel Processing:
    • স্ট্রিম চেইনিং প্যারালাল প্রসেসিংয়ের সাথে কাজ করতে পারে, যা বড় ডেটা সেটের সাথে কাজ করার সময় পারফর্মেন্স বাড়াতে সহায়ক।

Stream Chaining এর উদাহরণ

একটি সাধারণ Stream Chaining উদাহরণ

এই উদাহরণে, একটি সংখ্যার তালিকা ফিল্টার করা হবে, তাদের দ্বিগুণ করা হবে এবং তারপর তাদের যোগফল বের করা হবে।

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamChainingExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

        // Stream chaining for filtering, mapping, and summing
        int result = numbers.stream()
                            .filter(n -> n % 2 == 0)        // Filter even numbers
                            .map(n -> n * 2)                // Double each number
                            .reduce(0, Integer::sum);       // Sum the numbers

        System.out.println("Result: " + result); // Output will be 40 (2*2 + 4*2 + 6*2 + 8*2)
    }
}

ব্যাখ্যা:

  1. filter(n -> n % 2 == 0): শুধু even numbers ফিল্টার করা হচ্ছে।
  2. map(n -> n * 2): প্রত্যেকটি সংখ্যাকে দ্বিগুণ করা হচ্ছে।
  3. reduce(0, Integer::sum): সব সংখ্যাগুলোর যোগফল বের করা হচ্ছে।

আউটপুট:

Result: 40

Stream Chaining with Multiple Operations:

এই উদাহরণে, একটি স্ট্রিমে ফিল্টারিং, ম্যাপিং এবং সোর্স পরিবর্তন (sorting) করা হবে।

import java.util.Arrays;
import java.util.List;

public class AdvancedStreamChaining {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "elderberry");

        // Stream chaining with multiple operations
        long count = words.stream()
                          .filter(w -> w.length() > 5)         // Filter words with length > 5
                          .map(String::toUpperCase)            // Convert words to uppercase
                          .sorted()                            // Sort the words
                          .count();                            // Count the number of words

        System.out.println("Number of words longer than 5 characters: " + count);
    }
}

ব্যাখ্যা:

  1. filter(w -> w.length() > 5): এমন শব্দগুলিকে ফিল্টার করা হচ্ছে যার দৈর্ঘ্য ৫ এর বেশি।
  2. map(String::toUpperCase): প্রত্যেকটি শব্দকে uppercase করা হচ্ছে।
  3. sorted(): শব্দগুলোকে sorted করা হচ্ছে।
  4. count(): মোট সংখ্যক শব্দ গোনা হচ্ছে।

আউটপুট:

Number of words longer than 5 characters: 3

Stream Chaining এর অন্যান্য সুবিধা এবং ব্যবহার:

  1. Compactness:
    • স্ট্রিম চেইনিং কোডকে সংক্ষিপ্ত করে, কারণ আপনি এক লাইনে একাধিক অপারেশন একত্রে করতে পারেন।
  2. Parallel Stream Support:
    • স্ট্রিম চেইনিং parallel streams এর সাথে কাজ করতে সক্ষম, যা বৃহত্তর ডেটা সেটের জন্য কার্যকরী।
  3. Lazy Evaluation:
    • স্ট্রিম অপারেশনগুলি lazyভাবে প্রক্রিয়া হয়, অর্থাৎ যখনই প্রয়োজন হয়, তখনই ডেটা প্রক্রিয়া করা হয়।

  • Stream Chaining Java Streams API-র একটি শক্তিশালী বৈশিষ্ট্য যা ডেটা প্রক্রিয়াকরণকে আরো সহজ, পরিষ্কার, এবং কার্যকরী করে।
  • এটি functional programming স্টাইলের অনুসরণ করে, যেখানে আপনি ডেটা প্রক্রিয়া করার বিভিন্ন ধাপ একসাথে চেইন করতে পারেন।
  • Stream Chaining ব্যবহার করে আপনি ফিল্টারিং, ম্যাপিং, রিডিউসিং, এবং সোর্টিং ইত্যাদি বিভিন্ন স্ট্রিম অপারেশন একে অপরের সাথে সংযুক্ত করতে পারেন।
Content added By

FilterInputStream এবং FilterOutputStream হল Java I/O ক্লাস যা InputStream এবং OutputStream এর উপরে ফিল্টারিং ফিচার প্রদান করে। এগুলি decorator pattern এর মতো কাজ করে, যেখানে মূল স্ট্রিমের উপর অতিরিক্ত কার্যক্ষমতা যোগ করা হয়। এই ক্লাসগুলো বিশেষভাবে ব্যবহৃত হয় যখন আপনি স্ট্রিমের ডেটা প্রসেস করার সময় অতিরিক্ত কার্যাবলী যেমন ডেটা এনক্রিপশন, কমপ্রেশন, বা ডেটা ম্যানিপুলেশন করতে চান।


FilterInputStream এর ভূমিকা

FilterInputStream হল InputStream এর একটি সাবক্লাস যা ডেটার প্রবাহে ফিল্টারিং করতে ব্যবহৃত হয়। এটি মূলত এক বা একাধিক InputStream এর উপর অতিরিক্ত প্রক্রিয়া বা ফিল্টার অপারেশন করতে ব্যবহৃত হয়।

FilterInputStream এর মেথড:

  • read(): একটি বাইট পড়ে।
  • read(byte[] b): একাধিক বাইট পড়ে।
  • close(): স্ট্রিম বন্ধ করে।

FilterInputStream এর উদাহরণ:

import java.io.FilterInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class UpperCaseFilterInputStream extends FilterInputStream {

    public UpperCaseFilterInputStream(FileInputStream in) {
        super(in);
    }

    @Override
    public int read() throws IOException {
        int data = super.read();
        if (data == -1) {
            return -1; // End of stream
        }
        // Convert to uppercase if the character is lower case
        return Character.toUpperCase((char) data);
    }

    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("input.txt");
             UpperCaseFilterInputStream ucfis = new UpperCaseFilterInputStream(fis)) {
            int data;
            while ((data = ucfis.read()) != -1) {
                System.out.print((char) data); // Print upper case content from file
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ব্যাখ্যা:

  • এখানে UpperCaseFilterInputStream একটি কাস্টম ফিল্টার ইনপুট স্ট্রিম তৈরি করা হয়েছে যা ফাইলের সমস্ত ছোট অক্ষরকে বড় অক্ষরে রূপান্তর করবে।
  • FilterInputStream এর মাধ্যমে FileInputStream এর উপর একটি ফিল্টার যোগ করা হয়েছে।

আউটপুট:

HELLO WORLD!

FilterOutputStream এর ভূমিকা

FilterOutputStream হল OutputStream এর একটি সাবক্লাস যা আউটপুট স্ট্রিমে ডেটার উপর অতিরিক্ত প্রক্রিয়া বা ফিল্টারিং করতে ব্যবহৃত হয়। এটি মূলত OutputStream এর উপর ফিল্টার যোগ করে।

FilterOutputStream এর মেথড:

  • write(int b): একটি বাইট লেখে।
  • write(byte[] b): একাধিক বাইট লেখে।
  • close(): স্ট্রিম বন্ধ করে।

FilterOutputStream এর উদাহরণ:

import java.io.FilterOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ReverseFilterOutputStream extends FilterOutputStream {

    public ReverseFilterOutputStream(FileOutputStream out) {
        super(out);
    }

    @Override
    public void write(int b) throws IOException {
        super.write(~b); // Write the inverted byte to output stream
    }

    public static void main(String[] args) {
        try (FileOutputStream fos = new FileOutputStream("output.txt");
             ReverseFilterOutputStream rfos = new ReverseFilterOutputStream(fos)) {
            String data = "Hello, Java!";
            for (int i = 0; i < data.length(); i++) {
                rfos.write(data.charAt(i)); // Write reversed byte to output file
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ব্যাখ্যা:

  • এখানে ReverseFilterOutputStream একটি কাস্টম ফিল্টার আউটপুট স্ট্রিম তৈরি করা হয়েছে যা প্রতিটি বাইটের ইনভার্টেড মান ফাইলের মধ্যে লেখে।
  • FilterOutputStream এর মাধ্যমে FileOutputStream এর উপর একটি ফিল্টার যোগ করা হয়েছে।

ফলস্বরূপ ফাইল output.txt এর মধ্যে ডেটা ইনভার্টেড ফর্মে লেখা হবে।


FilterInputStream এবং FilterOutputStream এর মধ্যে পার্থক্য

বিষয়FilterInputStreamFilterOutputStream
প্রকারএটি InputStream এর উপর একটি ফিল্টার অপারেশন।এটি OutputStream এর উপর একটি ফিল্টার অপারেশন।
ব্যবহারডেটা পড়ার সময় ফিল্টার বা প্রক্রিয়া করার জন্য।ডেটা লেখার সময় ফিল্টার বা প্রক্রিয়া করার জন্য।
এটা কী করেইনপুট ডেটা ফিল্টার করে বা প্রক্রিয়া করে, যেমন টেক্সট বা বাইনারি।আউটপুট ডেটা ফিল্টার করে বা প্রক্রিয়া করে, যেমন টেক্সট বা বাইনারি।
উদাহরণক্যারেক্টার ক্যাপিটালাইজ করার জন্য বা ডেটা প্রক্রিয়া করার জন্য।ডেটা ইনভার্ট বা ফরম্যাট করা।

FilterInputStream এবং FilterOutputStream এর সুবিধা

  1. Customization: আপনি চাইলে ইনপুট এবং আউটপুট স্ট্রিমে কাস্টম ফিল্টারিং করতে পারেন।
  2. Data Transformation: স্ট্রিমের মাধ্যমে ডেটার মান পরিবর্তন বা রূপান্তর করার ক্ষমতা (যেমন এনক্রিপশন বা ডিক্রিপশন)।
  3. Efficient Data Processing: একাধিক স্ট্রিমে একই ধরনের ডেটা ফিল্টার বা প্রক্রিয়া করার সুবিধা।

FilterInputStream এবং FilterOutputStream এর সীমাবদ্ধতা

  1. Performance Overhead: অতিরিক্ত ফিল্টারিং অপারেশন অ্যাড করার ফলে কর্মক্ষমতা কিছুটা হ্রাস পেতে পারে।
  2. Limited Scope: এই ক্লাসগুলো শুধুমাত্র ইনপুট এবং আউটপুট স্ট্রিমের উপর প্রক্রিয়া করতে পারে এবং ফাইল বা স্ট্রিমের অন্যান্য উন্নত কার্যাবলীর জন্য আলাদা কনফিগারেশন বা কাস্টম ক্লাস প্রয়োজন।
  • FilterInputStream এবং FilterOutputStream স্ট্রিমের ডেটা প্রক্রিয়া এবং ফিল্টারিং করার জন্য খুবই কার্যকরী ক্লাস।
  • এগুলি I/O স্ট্রিমের উপর অতিরিক্ত কার্যক্রম যোগ করে, যেমন ডেটা এনক্রিপশন, ডিক্রিপশন, বা সাধারণ ফরম্যাটিং।
  • এই ক্লাসগুলির মাধ্যমে আপনি সহজে আপনার ডেটা প্রসেসিংয়ের প্রয়োজনীয় ফিল্টারিং বা রূপান্তর করতে পারেন।

Tuples ব্যবহার করে ফাইলের নাম, আকার, অথবা ডেটা স্ট্রিমের অন্যান্য প্রপার্টি সংরক্ষণ এবং পরিচালনা করতে পারেন, যা আপনাকে ডেটা প্রক্রিয়া এবং স্টোরেজ ব্যবস্থাপনায় আরও সহায়ক হতে পারে।

Content added By

Stream Chaining হলো একাধিক স্ট্রীম অপারেশন একে অপরের সাথে চেইন করা, অর্থাৎ এক স্ট্রীম অপারেশন থেকে আউটপুটকে পরবর্তী স্ট্রীম অপারেশনের ইনপুট হিসেবে ব্যবহার করা। Java 8 এ Streams API চালু হওয়ার পর, এটি Collection বা Array থেকে ডেটা প্রক্রিয়া করতে সহজ এবং কার্যকরী উপায়ে পরিণত হয়েছে।

Stream Chaining এর মাধ্যমে আপনি বিভিন্ন স্ট্রীম অপারেশন যেমন filter, map, reduce, collect ইত্যাদি একে অপরের সাথে চেইন করতে পারেন এবং ডেটা প্রসেসিংকে আরও পরিষ্কার ও সংক্ষিপ্ত করতে পারেন।


Stream Chaining এর সুবিধা

  1. একাধিক স্ট্রিম অপারেশন একত্রে প্রয়োগ: একাধিক স্ট্রিম অপারেশনকে একত্রে লেখা যায় যা কোডের সরলতা বাড়ায়।
  2. Lazy Evaluation: স্ট্রিম চেইনিংয়ে অপারেশনগুলো lazy evaluation অনুযায়ী কাজ করে, অর্থাৎ স্ট্রিমের মধ্যে যতটুকু ডেটা প্রক্রিয়া করা প্রয়োজন ততটুকু শুধুমাত্র প্রসেস করা হয়।
  3. Functional Style Programming: স্ট্রিম চেইনিং ফাংশনাল প্রোগ্রামিং স্টাইল অনুসরণ করে, যা কোডের উন্নত পরিষ্কারতা এবং কমপ্যাক্টনেস নিশ্চিত করে।

Stream Chaining উদাহরণ

১. List থেকে ডেটা ফিল্টার করা, ম্যাপ করা এবং সংগ্রহ করা

ধরা যাক, আমাদের কাছে একটি List আছে, এবং আমরা সেই লিস্ট থেকে শুধুমাত্র ইভেন নম্বর গুলি বের করতে চাই, তারপর প্রতিটি সংখ্যাকে দ্বিগুণ করে আউটপুটে ফিরিয়ে দেবো।

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamChainingExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // স্ট্রিম চেইনিং ব্যবহার করে ফিল্টার, ম্যাপ এবং কালেক্ট করা
        List<Integer> result = numbers.stream()
                                      .filter(n -> n % 2 == 0)          // ফিল্টার: শুধুমাত্র ইভেন নম্বর রাখুন
                                      .map(n -> n * 2)                  // ম্যাপ: প্রতিটি সংখ্যাকে দ্বিগুণ করুন
                                      .collect(Collectors.toList());    // কালেক্ট: লিস্টে সংগ্রহ করুন

        System.out.println(result); // আউটপুট: [4, 8, 12, 16, 20]
    }
}

ব্যাখ্যা:

  1. filter(n -> n % 2 == 0): শুধুমাত্র ইভেন নম্বর ফিল্টার করা হচ্ছে।
  2. map(n -> n * 2): প্রতিটি ইভেন নম্বর কে দ্বিগুণ করা হচ্ছে।
  3. collect(Collectors.toList()): ফলস্বরূপ ডেটা একটি নতুন List তে সংগ্রহ করা হচ্ছে।

২. String এর উপর Stream Chaining ব্যবহার করা

এখানে একটি উদাহরণ দেওয়া হয়েছে যেখানে String একটি List এর মধ্যে রূপান্তরিত হচ্ছে, এবং তারপর একটি নির্দিষ্ট কন্ডিশন মেনে স্ট্রিম চেইনিং কার্যকর করা হচ্ছে।

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamChainingStrings {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("java", "stream", "chaining", "example", "tutorial");

        // স্ট্রিম চেইনিং ব্যবহার করে বড় হাতের অক্ষরে রূপান্তর এবং লম্বা শব্দগুলির ফিল্টার
        List<String> result = words.stream()
                                   .filter(word -> word.length() > 4)       // ফিল্টার: ৪টির বেশি অক্ষর যুক্ত শব্দ
                                   .map(String::toUpperCase)                // ম্যাপ: শব্দগুলিকে বড় হাতের অক্ষরে রূপান্তর করা
                                   .collect(Collectors.toList());           // কালেক্ট: লিস্টে সংগ্রহ করা

        System.out.println(result); // আউটপুট: [STREAM, CHAINING, EXAMPLE, TUTORIAL]
    }
}

ব্যাখ্যা:

  1. filter(word -> word.length() > 4): শুধুমাত্র ৪টি বা তার বেশি অক্ষরের শব্দ ফিল্টার করা হচ্ছে।
  2. map(String::toUpperCase): প্রতিটি শব্দকে বড় হাতের অক্ষরে রূপান্তর করা হচ্ছে।
  3. collect(Collectors.toList()): প্রাপ্ত ফলাফল একটি List তে রূপান্তরিত করা হচ্ছে।

৩. Reduce এবং Collect ব্যবহার করে স্ট্রিম চেইনিং

এখন, একটি উদাহরণ দেখি যেখানে reduce() ফাংশন ব্যবহার করে সব সংখ্যার যোগফল বের করা হচ্ছে এবং তারপর ফলাফল লিস্টে সংগ্রহ করা হচ্ছে।

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class StreamReduceExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // স্ট্রিম চেইনিং ব্যবহার করে reduce এবং collect
        Optional<Integer> result = numbers.stream()
                                          .reduce((a, b) -> a + b);  // সব সংখ্যার যোগফল বের করা

        result.ifPresent(System.out::println); // আউটপুট: 15
    }
}

ব্যাখ্যা:

  1. reduce((a, b) -> a + b): সব সংখ্যার যোগফল বের করা হচ্ছে।
  2. Optional<Integer>: ফলস্বরূপ যোগফল Optional রিটার্ন হবে, কারণ স্ট্রিমে শূন্য উপাদান থাকতে পারে।

Stream Chaining এর সাথে Java Tuples ব্যবহার

Java Tuples ব্যবহার করে স্ট্রিম চেইনিং এর মাধ্যমে প্রাপ্ত ডেটার সাথে অতিরিক্ত প্রপার্টি সংরক্ষণ করতে পারেন। যেমন, আমরা Pair (যেমন Pair<String, Integer>) ব্যবহার করে বিভিন্ন প্রোপার্টি একত্রে সংরক্ষণ করতে পারি।

কোড উদাহরণ: Tuple ব্যবহার করে Stream Chaining

import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair;

public class TupleStreamChainingExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

        // Stream Chaining এর মাধ্যমে Tuple ব্যবহার করে প্রক্রিয়া করা
        List<Pair<String, Integer>> result = numbers.stream()
                                                    .filter(n -> n % 2 == 0)           // শুধুমাত্র ইভেন নম্বর ফিল্টার করা
                                                    .map(n -> Pair.of("Number", n * 2)) // প্রতি ইভেন নম্বরকে দ্বিগুণ করে Tuple তৈরি করা
                                                    .collect(Collectors.toList());      // লিস্টে সন্নিবেশ করা

        result.forEach(pair -> System.out.println(pair.getLeft() + ": " + pair.getRight()));
    }
}

আউটপুট:

Number: 4
Number: 8
Number: 12

এখানে:

  • Pair.of("Number", n * 2) ব্যবহার করে, আমরা প্রত্যেকটি ইভেন নম্বরের জন্য একটি Tuple তৈরি করেছি।
  • Pair এর প্রথম অংশে "Number" স্ট্রিং এবং দ্বিতীয় অংশে দ্বিগুণ করা নম্বর রাখা হয়েছে।

  • Stream Chaining একটি শক্তিশালী এবং প্রভাবশালী কৌশল যা Java Streams API এর মাধ্যমে একাধিক স্ট্রিম অপারেশন একত্রে করে ডেটা প্রক্রিয়া করা সহজ করে তোলে।
  • Java Tuples ব্যবহার করে, আপনি স্ট্রিম চেইনিংয়ের ফলস্বরূপ ডেটা এবং তার প্রোপার্টি একত্রে সংরক্ষণ করতে পারেন, যা কোডকে আরও পরিষ্কার এবং কার্যকরী করে তোলে।
Content added By
Promotion

Are you sure to start over?

Loading...