এই ব্লগ পোস্টে আমরা জাভা ৮ স্ট্রিমস বৈশিষ্ট্যগুলো নিয়ে আলোচনা করব এবং অনেক কোড উদাহরণ প্রদান করব।
জাভা স্ট্রিমস কেন ব্যবহার করবেন?
স্ট্রিমসের কিছু সুবিধা:
- স্ট্রিমস আপনাকে আরও দক্ষ জাভা প্রোগ্রামার বানাবে (খুব কম লাইনের কোডে আপনি স্ট্রিমস ব্যবহার করে অনেক কিছু অর্জন করতে পারবেন)।
- এই ল্যাম্বডা এক্সপ্রেশনগুলোর ব্যাপক ব্যবহার করে, যা এক ধরনের ডিসপোজেবল ফাংশন।
- প্যারালেলস্ট্রিমস বড় ডেটাসেটের জন্য সহজে মাল্টি-থ্রেডেড অপারেশন সক্ষম করে।
স্ট্রিমস পাইপলাইন
বেশিরভাগ ক্ষেত্রে, একটি স্ট্রিমস পাইপলাইন নিম্নলিখিত موارد নিয়ে গঠিত:
- সোর্স (যেখানে থেকে আপনার ডেটা ফ্লো করে)
- শূন্য বা অধিক ইন্টারমিডিয়েট অপারেশন
- এবং একটি টার্মিনাল অপারেশন

সোর্স একটি এলিমেন্টের স্ট্রিম তৈরি করে।
এই এলিমেন্টের স্ট্রিম ফিল্টার, সর্ট, ম্যাপ করা যেতে পারে বা প্রতিটি এলিমেন্টে ভিন্ন-भিন্ন সিরিজ অপারেশন প্রয়োগ করা যেতে পারে।
শেষে, এটি কালেক্ট বা রিডিউস বা অন্য কোনো টার্মিনাল অপারেশন হতে পারে কিন্তু শুধু একটি টার্মিনাল অপারেশনই পারফর্ম করা হয়।
স্ট্রিম সোর্স
স্ট্রিম সোর্স কালেকশন, লিস্ট, সেট, int, long, double, স্ট্রিং এর অ্যারে ইত্যাদি থেকে আসতে পারে।
স্ট্রিম অপারেশন
স্ট্রিম অপারেশন হয় ইন্টারমিডিয়েট অথবা টার্মিনাল:
- ইন্টারমিডিয়েট অপারেশন যেমন filter, map, বা sort একটি স্ট্রিম রিটার্ন করে যাতে আমরা একাধিক ইন্টারমিডিয়েট অপারেশন চেইন করতে পারি।
- টার্মিনাল অপারেশন একটি স্ট্রিম রিসিভ করে এবং তারা বায়ড রিটার্ন করতে পারে অথবা নন-স্ট্রিম রেজাল্ট রিটার্ন করতে পারে যেমন রিডাকশন, উদাহরণস্বরূপ আইটেমগুলোকে একটি লিস্টে রিডিউস করা।
ইন্টারমিডিয়েট অপারেশন
- শূন্য বা অধিক ইন্টারমিডিয়েট অপারেশন অনুমোদিত।
- অর্ডার গুরুত্বপূর্ণ; বড় ডেটাসেটের জন্য: ফাস্ট ফিল্টার তারপর সর্ট বা ম্যাপ।
- খুব বড় ডেটাসেটের জন্য ParallelStream ব্যবহার করুন মাল্টিপল থ্রেড সক্ষম করার জন্য।
কিছু ইন্টারমিডিয়েট অপারেশন অন্তর্ভুক্ত:
- anyMatch()
- distinct()
- filter()
- findFirst()
- flatMap()
- map()
- skip()
- sorted()
টার্মিনাল অপারেশন
শুধু একটি টার্মিনাল অপারেশন অনুমোদিত।
- forEach প্রতিটি এলিমেন্টে একই ফাংশন প্রয়োগ করে উদাহরণস্বরূপ প্রতিটি এলিমেন্ট প্রিন্ট করা।
- collect সমস্ত এলিমেন্ট একটি কালেকশন বা লিস্ট বা অ্যারেতে সংরক্ষণ করে।
- অন্য সব অপশন স্ট্রিমকে একটি সিঙ্গেল সামারি এলিমেন্টে রিডিউস করে।
রিডাক্ট ফাংশনের কিছু উদাহরণ:
- count()
- max()
- min()
- reduce()
জাভা স্ট্রিমস কোড উদাহরণ
এখন উপরের কনসেপ্টগুলো কোড উদাহরণে দেখি।
ইন্টিজার স্ট্রিম
প্রথম উদাহরণটি শুধু একটি ইন্টিজার স্ট্রিম। আমরা IntStream ক্লাস এবং এর রেঞ্জ ফাংশন ব্যবহার করে একটি ইন্টিজার স্ট্রিম তৈরি করব যা আমাদের ইন্টিজারদের একটি রেঞ্জ দেবে।
forEach আমাদের টার্মিনাল অপারেশন। প্রতিটি আইটেমের জন্য, আমরা সেটি প্রিন্ট করব।
import java.io.IOException;
import java.util.stream.IntStream;
public class JavaStreams {
public static void main(String[] args) throws IOException {
IntStream.range(1, 10).forEach(System.out::print);
System.out.println();
}
}
আউটপুট:
123456789
স্কিপসহ ইন্টিজার স্ট্রিম
দ্বিতীয় উদাহরণে একটি ইন্টিজার স্ট্রিম ব্যবহার করা হয়েছে কিন্তু এখানে skip() যোগ করা হয়েছে, তাই এই কেসে আমরা আমাদের স্ট্রিমের প্রথম ৫টি এলিমেন্ট স্কিপ করব।
এটি শুধু ৬ থেকে ৯ পর্যন্ত এলিমেন্ট প্রিন্ট করবে। আমরা একটি সিম্পল ল্যাম্বডা এক্সপ্রেশনও ব্যবহার করছি আইটেম প্রিন্ট করার জন্য।
import java.io.IOException;
import java.util.stream.IntStream;
public class JavaStreams {
public static void main(String[] args) throws IOException {
IntStream.range(1, 10).skip(5).forEach(x -> System.out.println(x));
System.out.println();
}
}
আউটপুট:
6 7 8 9
সামসহ ইন্টিজার স্ট্রিম
তৃতীয় উদাহরণে, আমরা আবার IntStream ব্যবহার করি আমাদের অবজেক্টের স্ট্রিম তৈরি করতে, কিন্তু এখানে সেটি একটি println() স্টেটমেন্টের ভেতর প্যারামিটার হিসেবে রাখা হয়েছে।
আমরা যা প্রিন্ট করব সেটি হল ১ থেকে ৫ পর্যন্ত রেঞ্জের যোগফল, অর্থাৎ ১ ২ ৩ ৪ এর যোগফল এটি শুধু সেই নাম্বারগুলোর যোগফল প্রিন্ট করবে:
import java.io.IOException;
import java.util.stream.IntStream;
public class JavaStreams {
public static void main(String[] args) throws IOException {
System.out.println(IntStream.range(1, 5).sum());
System.out.println();
}
}
আউটপুট:
10
Stream.of
পরবর্তী উদাহরণটি Stream.of ফাংশন ব্যবহার করে, যা খুব হ্যান্ডি কারণ এতে আপনি ইন্টিজার, ফ্লোটিং পয়েন্ট ভ্যালু বা স্ট্রিং বা এমনকি অবজেক্ট স্ট্রিম করতে পারেন।
এই উদাহরণে, আমরা শুধু একটি সিধা অ্যালফাবেটিক্যাল সর্ট করব তারপর findFirst() ফাংশন ব্যবহার করে প্রথম আইটেম খুঁজে বের করব। তারপর, লিস্টের প্রথম আইটেমটি প্রিন্ট করব।
import java.io.IOException;
import java.util.stream.Stream;
public class JavaStreams {
public static void main(String[] args) throws IOException {
Stream.of("Ava", "Aneri", "Alberto").sorted().findFirst().ifPresent(System.out::println);
}
}
আউটপুট:
Alberto
অ্যারে থেকে স্ট্রিম, সর্ট, ফিল্টার এবং প্রিন্ট
আমাদের পরবর্তী উদাহরণে, আমরা একটি অ্যারে থেকে স্ট্রিম করব। তারপর সর্ট, ফিল্টার এবং প্রিন্ট করব।
এখানে, আমরা শুধু সেই আইটেমগুলো ফিল্টার আউট করব যেগুলো s দিয়ে শুরু হয়।
আমরা একটি ল্যাম্বডা এক্সপ্রেশন ব্যবহার করব যা X নেবে প্রতিটি নাম হিসেবে এবং তারপর চেক করব কোনগুলো s লেটার দিয়ে শুরু হয়েছে এবং সেগুলো পাস করবে।
তারপর আমরা সেগুলো সর্ট করব এবং সেই সর্ট পাস করা প্রতিটি আইটেমের জন্য প্রিন্ট করব।
import java.io.IOException;
import java.util.Arrays;
public class JavaStreams {
public static void main(String[] args) throws IOException {
String[] names = {"Al", "Ankit", "Kushal", "Brent", "Sarika", "amanda", "Hans", "Shivika", "Sarah"};
Arrays.stream(names).filter(x -> x.startsWith("S")).sorted().forEach(System.out::println);
}
}
আউটপুট:
Sarah Sarika Shivika
ইন্টিজার অ্যারের গড়
এখন দেখা যাক কিভাবে একটি ইন্ট অ্যারের স্কোয়ারের গড় বের করা যায়।
এখানে, আমরা Arrays.stream() ফাংশন ব্যবহার করি ইন্টিজারগুলো স্ট্রিম করতে এবং তারপর map() ব্যবহার করি প্রতিটি আইটেমকে এর স্কোয়ারে ম্যাপ করতে।
import java.util.Arrays;
public class JavaStreams {
public static void main(String[] args) {
Arrays.stream(new int[] {2, 4, 6, 8, 10}).map(x -> x * x).average().ifPresent(System.out::println);
}
}
আউটপুট:
44.0
নোট: এটি ইন্টিজার না প্রিন্ট করে ডাবল প্রিন্ট করে।
লিস্ট থেকে স্ট্রিম, ফিল্টার এবং প্রিন্ট
এই উদাহরণে, আমরা একটি লিস্ট থেকে স্ট্রিম করব, সেই আইটেমগুলো ফিল্টার করব এবং তারপর প্রিন্ট করব।
নোট করুন map() ফাংশনের ভিতরে, আমরা সব নামকে লোয়ারকেসে কনভার্ট করব।
import java.util.Arrays;
import java.util.List;
public class JavaStreams {
public static void main(String[] args) {
List people = Arrays.asList("Al", "Ankit", "Brent", "Sarika", "amanda", "Hans", "Shivika", "Sarah");
people.stream().map(String::toLowerCase).filter(x -> x.startsWith("a")).forEach(System.out::println);
}
}
আউটপুট:
al ankit amanda
আমরা দেখতে পাচ্ছি তিনটি নাম আছে যা a দিয়ে শুরু হয়েছে এবং সেগুলো সব লোয়ারকেসে।
টেক্সট ফাইল থেকে স্ট্রিম রো, সর্ট, ফিল্টার, এবং প্রিন্ট
আমাদের পরবর্তী উদাহরণে, আমরা একটি টেক্সট ফাইল থেকে রো স্ট্রিম করব। সর্ট, ফিল্টার এবং প্রিন্ট করব।
মান লইয়া যাক আমাদের bands.txt নামের একটি ফাইল আছে যện محتويات নিচে দেখানো হয়েছে:
Rolling Stones
Lady Gaga
Jackson Browne
Maroon 5
Arijit Singh
Elton John
John Mayer
CCR
Eagles
Pink
Aerosmith
Adele
Taylor Swift
আমরা Files.lines() ব্যবহার করব আমাদের স্ট্রিম তৈরি করতে যা ফাইলের প্রতিটি লাইনের জন্য একটি স্ট্রিং স্ট্রিম দেবে।
একবার আমাদের স্ট্রিম পাওয়া যাক, আমরা সেগুলো সর্ট করব এবং ১৩ ক্যারেক্টার سے বড় আইটেমগুলো ফিল্টার আউট করব এবং বাকি আইটেমগুলো প্রিন্ট করব।
শেষে, আমাদের ফাইলটি ক্লোজ করতে হবে তাই আমরা bands.close করব।
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class JavaStreams {
public static void main(String[] args) throws IOException {
Stream bands = Files.lines(Paths.get("bands.txt"));
bands.sorted().filter(x -> x.length() > 13).forEach(System.out::println);
bands.close();
}
}
আউটপুট:
Jackson Browne
Rolling Stones
আমরা দুটি ব্যান্ড পেলাম যাদের ১৩ ক্যারেক্টার سے বেশি।
টেক্সট ফাইল থেকে স্ট্রিম রো এবং লিস্টে সংরক্ষণ
এই উদাহরণের জন্য, আমরা উপরের মতো একই টেক্সট ফাইল ব্যবহার করব।
আমরা চাই jit লেটারগুলো ধারণকারী আইটেমগুলো ফিল্টার আউট করতে, x.contains() ব্যবহার করে যা শুধু একটি স্ট্রিং ফাংশন।
.collect() ব্যবহার করে আমরা jit লেটারवाले সবগুলোকে একটি লিস্টে যোগ করব।
একবার লিস্ট পাওয়া যাক, আমরা forEach অপারেটর ব্যবহার করে আইটেমগুলো প্রিন্ট করব।
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
public class JavaStreams {
public static void main(String[] args) throws IOException {
List bands2 = Files.lines(Paths.get("bands.txt")).filter(x -> x.contains("jit")).collect(Collectors.toList());
bands2.forEach(x -> System.out.println(x));
}
}
আউটপুট:
Arijit Singh
সিএসভি ফাইল থেকে স্ট্রিম রো এবং কাউন্ট
এই উদাহরণে, আমরা একটি সিএসভি ফাইল থেকে রো স্ট্রিম করব এবং আমরা ভালো রোগুলো কাউন্ট করব।
মান লইয়া যাক আমাদের data.txt নামের একটি ফাইল আছে যện নিচের কন্টেন্ট:
A,12,3.7
B,17,2.8
C,14,1.9
D,23,2.7
E
F,18,3.4
এখানে, রো E-তে কোনো ডেটা নেই, তাই আমরা সেটি আমাদের স্ট্রিম থেকে বাদ দিতে চাই।
নিচের কোডে, আমরা প্রতিটি রো পড়ব তারপর কমাতে স্প্লিট করব একটি অ্যারেতে যাতে প্রতিটি রো আইটেমের একটি অ্যারে হয়ে যায়।
তারপর আমরা একটি ফিল্টার প্রয়োগ করব যাতে তিনটি আইটেম নাও থাকা রোগুলো ফিল্টার আউট হয়।
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class JavaStreams {
public static void main(String[] args) throws IOException {
Stream rows1 = Files.lines(Paths.get("data.txt"));
int rowCount = (int) rows1.map(x -> x.split(",")).filter(x -> x.length == 3).count();
System.out.println(rowCount + " rows.");
rows1.close();
}
}
আউটপুট:
5 rows
রিডাকশন - যোগফল
এই উদাহরণটি আপনাকে দেখাবে কিভাবে রিডাকশন ব্যবহার করতে হয়। আমরা একটি যোগফলে রিডিউস করব। এখানে, আমাদের একটি ডাবল স্ট্রিম আছে Stream.of() ফাংশন ব্যবহার করে। আমরা তিনটি ডাবল তিনটি আলাদা আর্গুমেন্টে ডিফাইন করেছি এবং reduce ফাংশন ব্যবহার করব।
import java.util.stream.Stream;
public class JavaStreams {
public static void main(String[] args) {
double total = Stream.of(7.3, 1.5, 4.8).reduce(0.0, (Double a, Double b) -> a + b);
System.out.println("Total = " + total);
}
}
আউটপুট:
13.600000000000001