সমাধান করার জন্য আমাদের একই সমস্যা ছিল। আমরা সিস্টেম স্ট্রিমির চেয়ে বড় স্ট্রিমটি নিতে চেয়েছিলাম (একটি ডাটাবেসে সমস্ত বস্তুর মাধ্যমে পুনরাবৃত্তি করা) এবং যথাসম্ভব যথাক্রমে অর্ডারটিকে এলোমেলো করে দিতে - আমরা ভেবেছিলাম 10,000 টি আইটেম বাফার করা এবং এলোমেলো করে দেওয়া ঠিক হবে be
লক্ষ্যটি একটি ফাংশন যা একটি স্ট্রিম নিয়েছিল।
এখানে প্রস্তাবিত সমাধানগুলির মধ্যে অনেকগুলি বিকল্প রয়েছে বলে মনে হচ্ছে:
- বিভিন্ন নন-জাভা 8 টি অতিরিক্ত গ্রন্থাগার ব্যবহার করুন
- কোনও স্ট্রিম নয় এমন কোনও কিছু দিয়ে শুরু করুন - যেমন একটি এলোমেলো অ্যাক্সেসের তালিকা
- একটি স্ট্রিম রয়েছে যা একটি স্প্লিট্রেটারে সহজেই বিভক্ত করা যায়
আমাদের প্রবৃত্তিটি মূলত একটি কাস্টম সংগ্রাহক ব্যবহার করার জন্য ছিল তবে এর অর্থ স্ট্রিমিং বাদ দেওয়া। উপরের কাস্টম সংগ্রাহকের সমাধানটি খুব ভাল এবং আমরা এটি প্রায় ব্যবহার করেছি।
এখানে একটি সমাধান যা সত্য যে ব্যবহার করে Cheats Streamগুলি আপনি একটি দিতে পারে Iteratorযা আপনি যেমন ব্যবহার করতে পারেন এড়িয়ে যাওয়ার জন্য একটি ডিম পাড়া আপনি কিছু অতিরিক্ত যে স্ট্রিম সমর্থন করি না করতে দেওয়া হয়। Iteratorএকটি স্ট্রিম জাভা 8 আরেকটি বিট ব্যবহার করে রূপান্তরিত ফিরে এসেছে StreamSupportজাদু।
public class BatchingIterator<T> implements Iterator<List<T>> {
public static <T> Stream<List<T>> batchedStreamOf(Stream<T> originalStream, int batchSize) {
return asStream(new BatchingIterator<>(originalStream.iterator(), batchSize));
}
private static <T> Stream<T> asStream(Iterator<T> iterator) {
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(iterator,ORDERED),
false);
}
private int batchSize;
private List<T> currentBatch;
private Iterator<T> sourceIterator;
public BatchingIterator(Iterator<T> sourceIterator, int batchSize) {
this.batchSize = batchSize;
this.sourceIterator = sourceIterator;
}
@Override
public boolean hasNext() {
prepareNextBatch();
return currentBatch!=null && !currentBatch.isEmpty();
}
@Override
public List<T> next() {
return currentBatch;
}
private void prepareNextBatch() {
currentBatch = new ArrayList<>(batchSize);
while (sourceIterator.hasNext() && currentBatch.size() < batchSize) {
currentBatch.add(sourceIterator.next());
}
}
}
এটির ব্যবহারের একটি সাধারণ উদাহরণটি দেখতে পাবেন:
@Test
public void getsBatches() {
BatchingIterator.batchedStreamOf(Stream.of("A","B","C","D","E","F"), 3)
.forEach(System.out::println);
}
উপরের প্রিন্ট
[A, B, C]
[D, E, F]
আমাদের ব্যবহারের ক্ষেত্রে, আমরা ব্যাচগুলি এলোমেলো করে তারপরে স্ট্রিম হিসাবে রাখতে চেয়েছিলাম - দেখে মনে হয়েছিল:
@Test
public void howScramblingCouldBeDone() {
BatchingIterator.batchedStreamOf(Stream.of("A","B","C","D","E","F"), 3)
.map(list -> {
Collections.shuffle(list); return list; })
.flatMap(List::stream)
.forEach(System.out::println);
}
এটি এমন কিছু আউটপুট দেয় (এটি এলোমেলোভাবে তৈরি হয়, প্রতিবারের চেয়ে আলাদা)
A
C
B
E
D
F
এখানে সিক্রেট সস হ'ল সর্বদা একটি স্রোত থাকে, তাই আপনি হয় একটি ব্যাচের স্রোতে পরিচালনা করতে পারেন, বা প্রতিটি ব্যাচে কিছু করতে পারেন এবং তারপরে flatMapএটি আবার স্ট্রিমে ফিরে যেতে পারেন। আরও ভাল করে, উপরে শুধুমাত্র সব চূড়ান্ত হিসাবে সঞ্চালিত হয় forEachবা collectবা অন্যান্য সসীম এক্সপ্রেশন খিঁচ প্রবাহ মাধ্যমে ডেটা।
দেখা যাচ্ছে যে একটি স্ট্রিমের iteratorএকটি বিশেষ ধরণের সমাপ্তি অপারেশন এবং পুরো স্ট্রিমটি চলমান এবং স্মৃতিতে আসে না! একটি উজ্জ্বল ডিজাইনের জন্য জাভা 8 জনকে ধন্যবাদ!