আমি অন্য দিনটি চালিয়ে গিয়েছিলাম এমন আরও একটি কৌশল এখানে রয়েছে:
Collections.nCopies(8, 1)
.stream()
.forEach(i -> System.out.println(i));
Collections.nCopies
কলের জন্য একটি সৃষ্টি List
ধারণকারী n
যাই হোক না কেন মান প্রদান কপি। এক্ষেত্রে এটি বাক্সযুক্ত Integer
মান ১। অবশ্যই এটি n
উপাদানগুলির সাথে তালিকাগুলি তৈরি করে না ; এটি একটি "ভার্চুয়ালাইজড" তালিকা তৈরি করে যা কেবলমাত্র মান এবং দৈর্ঘ্য ধারণ করে এবং get
সীমার মধ্যে যে কোনও কল কেবল মানটি দেয়। nCopies
পদ্ধতি হয়েছে প্রায় যেহেতু সংগ্রহগুলি ফ্রেমওয়ার্ক JDK 1.2 উপায় ফিরে চালু করা হয়। অবশ্যই, জাভা এসই 8 এ এর ফলাফল থেকে একটি স্ট্রিম তৈরি করার ক্ষমতা যুক্ত করা হয়েছিল।
বড় চুক্তি, একই সংখ্যক লাইনের একই জিনিসটি করার আরেকটি উপায়।
তবে এই কৌশলটি দ্রুত IntStream.generate
এবং IntStream.iterate
পদ্ধতির চেয়ে দ্রুত এবং আশ্চর্যজনকভাবে এটি IntStream.range
পদ্ধতির চেয়েও দ্রুত than
কারণ iterate
এবং generate
ফলাফল সম্ভবত খুব অবাক হয় না। স্ট্রিমস ফ্রেমওয়ার্ক (প্রকৃতপক্ষে, এই স্ট্রিমগুলির জন্য স্প্লিটেটরগুলি) এই ধারণার উপর ভিত্তি করে তৈরি করা হয়েছে যে ল্যাম্বডাস প্রতিটিবারই সম্ভাব্যভাবে বিভিন্ন মান তৈরি করবে এবং তারা একটি সীমাহীন ফলাফল তৈরি করবে। এটি সমান্তরাল বিভাজন বিশেষ করে কঠিন করে তোলে। iterate
পদ্ধতি কারণ প্রতিটি কলের আগের ফল প্রয়োজন এই ক্ষেত্রে জন্য সমস্যাযুক্ত। সুতরাং স্ট্রিমগুলি বারবার ধ্রুবক তৈরির জন্য খুব ভাল করে না generate
এবং ব্যবহার করে iterate
না।
অপেক্ষাকৃত দুর্বল অভিনয় range
বিস্ময়কর। এটিও ভার্চুয়ালাইজড, সুতরাং উপাদানগুলি মেমরির মধ্যে আসলে বিদ্যমান থাকে না এবং আকারটি সামনে জানা যায়। এটি দ্রুত এবং সহজেই সমান্তরাল স্প্লিট্রেটারের তৈরি করা উচিত। তবে এটি আশ্চর্যজনকভাবে খুব ভাল করেনি। সম্ভবত কারণটি হ'ল range
পরিসরের প্রতিটি উপাদানটির জন্য একটি মান গণনা করতে হবে এবং তারপরে একটি ফাংশন কল করতে হবে। তবে এই ফাংশনটি কেবল তার ইনপুটটিকে উপেক্ষা করে একটি ধ্রুবককে ফিরিয়ে দেয়, তাই আমি আশ্চর্য হয়েছি যে এটি ইনলাইনড এবং হত্যা করা হয়নি।
Collections.nCopies
কৌশল যেহেতু কোন আদিম বিশেষায়িত হয়, যাতে মান হ্যান্ডেল করার জন্য আনবক্সিং / বক্সিং কি আছে List
। যেহেতু প্রতিবার মান একই হয় তাই এটি মূলত একবারে বক্স করা হয় এবং সেই বাক্সটি সমস্ত n
অনুলিপি দ্বারা ভাগ করা হয় । আমি সন্দেহ করি বক্সিং / আনবক্সিং উচ্চতর অনুকূলিত, এমনকি স্বতঃস্ফূর্ত এবং এটি ভালভাবে ইনলাইন করা যেতে পারে।
কোডটি এখানে:
public static final int LIMIT = 500_000_000;
public static final long VALUE = 3L;
public long range() {
return
LongStream.range(0, LIMIT)
.parallel()
.map(i -> VALUE)
.map(i -> i % 73 % 13)
.sum();
}
public long ncopies() {
return
Collections.nCopies(LIMIT, VALUE)
.parallelStream()
.mapToLong(i -> i)
.map(i -> i % 73 % 13)
.sum();
}
এবং এখানে জেএমএইচ ফলাফল রয়েছে: (2.8GHz কোর 2 ডুও)
Benchmark Mode Samples Mean Mean error Units
c.s.q.SO18532488.ncopies thrpt 5 7.547 2.904 ops/s
c.s.q.SO18532488.range thrpt 5 0.317 0.064 ops/s
এনসিপিগুলি সংস্করণে যথেষ্ট পরিমাণে বৈকল্পিক রয়েছে তবে সামগ্রিকভাবে এটি পরিসীমা সংস্করণের তুলনায় আরামদায়কভাবে 20x দ্রুত বলে মনে হচ্ছে। (যদিও আমি বিশ্বাস করতে বেশ আগ্রহী যে আমি কিছু ভুল করেছি।)
nCopies
কৌশলটি কতটা ভাল কাজ করে তা নিয়ে আমি অবাক । অভ্যন্তরীণভাবে এটি খুব বেশি বিশেষ করে না, ভার্চুয়ালাইজড তালিকার প্রবাহটি কেবল ব্যবহার করে প্রয়োগ করা হচ্ছে IntStream.range
! আমি প্রত্যাশা করেছি যে এটি দ্রুত যাওয়ার জন্য একটি বিশেষায়িত স্প্লিটেটর তৈরি করা প্রয়োজন, তবে এটি ইতিমধ্যে বেশ ভাল বলে মনে হচ্ছে।