জাভা 8, একটি নতুন পদ্ধতি String.chars()
যার একটি স্ট্রিম ফেরৎ int
গুলি ( IntStream
) যে চরিত্র কোড প্রতিনিধিত্ব করে। আমার ধারণা অনেক লোক char
এর পরিবর্তে এখানে একটি স্ট্রিম আশা করবে expect এইভাবে এপিআই ডিজাইন করার প্রেরণাটি কী ছিল?
জাভা 8, একটি নতুন পদ্ধতি String.chars()
যার একটি স্ট্রিম ফেরৎ int
গুলি ( IntStream
) যে চরিত্র কোড প্রতিনিধিত্ব করে। আমার ধারণা অনেক লোক char
এর পরিবর্তে এখানে একটি স্ট্রিম আশা করবে expect এইভাবে এপিআই ডিজাইন করার প্রেরণাটি কী ছিল?
উত্তর:
অন্যরা যেমন ইতিমধ্যে উল্লেখ করেছে, এর পিছনে নকশার সিদ্ধান্তটি ছিল পদ্ধতি এবং শ্রেণীর বিস্ফোরণ রোধ করা।
তবুও, ব্যক্তিগতভাবে আমি মনে করি এটি একটি খুব খারাপ সিদ্ধান্ত ছিল, এবং তাদের উচিত না দেওয়া উচিত CharStream
, যা যুক্তিসঙ্গত, পরিবর্তে বিভিন্ন পদ্ধতি না করে chars()
, আমি ভেবে দেখব:
Stream<Character> chars()
, এটি বাক্স অক্ষরগুলির একটি স্ট্রিম সরবরাহ করে, এতে কিছু হালকা পারফরম্যান্স পেনাল্টি থাকবে।IntStream unboxedChars()
, যা পারফরম্যান্স কোডের জন্য ব্যবহৃত হবে।তবে কেন তার দিকে নজর দেওয়ার পরিবর্তে বর্তমানে এটি এইভাবে করা হচ্ছে তা , আমি মনে করি যে এই জবাবটি জাভা 8 এর সাথে আমরা যে এপিআই পেয়েছি তা দিয়ে এটি করার কোনও উপায় দেখানোতে ফোকাস করা উচিত।
জাভা 7 এ আমি এটি এটি করতাম:
for (int i = 0; i < hello.length(); i++) {
System.out.println(hello.charAt(i));
}
এবং আমি মনে করি জাভা 8 এ এটি করার একটি যুক্তিসঙ্গত পদ্ধতি নিম্নলিখিত:
hello.chars()
.mapToObj(i -> (char)i)
.forEach(System.out::println);
এখানে আমি একটি পেয়েছি IntStream
এবং ল্যাম্বদার মাধ্যমে এটি কোনও বস্তুতে ম্যাপ i -> (char)i
করব, এটি এটি স্বয়ংক্রিয়ভাবে এটিকে একটিতে বক্স করবেStream<Character>
এবং তারপরে আমরা যা চাই তা করতে পারি, এবং এখনও পদ্ধতি রেফারেন্সকে একটি প্লাস হিসাবে ব্যবহার করি।
সচেতন হতে হবে যদিও আপনি আবশ্যক না mapToObj
, যদি তোমাকে ভুলে এবং ব্যবহার map
, তারপর কিছুই অভিযোগ হবে, কিন্তু আপনি এখনও একটি দিয়ে শেষ হবে IntStream
, এবং আপনি হতাশ কেন এটা স্ট্রিং অক্ষর প্রতিনিধিত্বমূলক পরিবর্তে পূর্ণসংখ্যা মান ছাপে বন্ধ করেছিলাম সেখান থেকে হতে পারে।
জাভা 8 এর জন্য অন্যান্য কুরুচিপূর্ণ বিকল্প:
একটিতে থাকা এবং IntStream
চূড়ান্তভাবে সেগুলি মুদ্রণ করতে ইচ্ছুক হয়ে আপনি মুদ্রণের জন্য কোনও পদ্ধতি রেফারেন্স ব্যবহার করতে পারবেন না:
hello.chars()
.forEach(i -> System.out.println((char)i));
তদুপরি, আপনার নিজস্ব পদ্ধতিতে পদ্ধতির রেফারেন্স ব্যবহার করে আর কাজ হয় না! নিম্নোক্ত বিবেচনা কর:
private void print(char c) {
System.out.println(c);
}
এবং তারপর
hello.chars()
.forEach(this::print);
এটি একটি সংকলন ত্রুটি দেবে, কারণ সম্ভবত একটি ক্ষতিকারক রূপান্তর রয়েছে।
উপসংহার:
এপিআই কারণ যোগ করার জন্য অনুপস্থিত না এই পদ্ধতি পরিকল্পনা করা হয়েছিল CharStream
, আমি ব্যক্তিগতভাবে মনে করি যে পদ্ধতি একটি ফিরতি উচিত Stream<Character>
, এবং কার্যসংক্রান্ত বর্তমানে ব্যবহার করা mapToObj(i -> (char)i)
একটি অন IntStream
তাঁদের সঙ্গে ঠিকমত কাজ পাবে।
codePoints()
পরিবর্তে ব্যবহার করা chars()
এবং আপনি ইতিমধ্যে int
কোড পয়েন্টের জন্য ইতিমধ্যে প্রচুর গ্রন্থাগার ফাংশনগুলি দেখতে পাবেন char
, যেমন সমস্ত পদ্ধতির java.lang.Character
পাশাপাশি পদ্ধতি StringBuilder.appendCodePoint
ইত্যাদি This এই সমর্থনটি তখন থেকেই বিদ্যমান jdk1.5
।
String
বা এর মধ্যে সারোগেট জোড়া হিসাবে উপস্থাপিত হয় char[]
। আমি বাজি ধরব যে বেশিরভাগ char
প্রসেসিং কোড সার্ভেট জোড়াকে ভুলভাবে ছড়িয়ে দেয়।
void print(int ch) { System.out.println((char)ch); }
এবং তারপরে আপনি পদ্ধতির উল্লেখগুলি ব্যবহার করতে পারেন।
Stream<Character>
প্রত্যাখ্যান করা হয়েছিল তার জন্য আমার উত্তর দেখুন ।
Skiwi থেকে উত্তর ইতিমধ্যে প্রধান পয়েন্ট অনেক আচ্ছাদিত। আমি আরও কিছুটা পটভূমি পূরণ করব।
যে কোনও এপিআইয়ের ডিজাইন হ'ল ট্রেড অফসের একটি সিরিজ। জাভাতে, একটি জটিল সমস্যা হ'ল অনেক আগে থেকেই তৈরি নকশার সিদ্ধান্ত নিয়ে কাজ করা।
প্রিমিটিভগুলি জাভাতে রয়েছে 1.0 থেকে since তারা জাভাটিকে একটি "অপরিষ্কার" অবজেক্ট-ভিত্তিক ভাষা বানায়, যেহেতু আদিম বস্তু নয়। আমি বিশ্বাস করি, বস্তু-ভিত্তিক বিশুদ্ধতার ব্যয়ে কর্মক্ষমতা উন্নত করার এক প্রাকৃতিক সিদ্ধান্ত ছিল believe
এটি এমন একটি বাণিজ্য যা আমরা এখনও প্রায় 20 বছর পরে আজকের সাথে বাস করছি। জাভা 5-এ যুক্ত অটোবক্সিং বৈশিষ্ট্যটি বেশিরভাগ ক্ষেত্রে বক্সিং এবং আনবক্সিং পদ্ধতি কলগুলির সাথে সোর্স কোডের বিশৃঙ্খলা দূর করতে পারে তবে ওভারহেড এখনও সেখানে রয়েছে। অনেক ক্ষেত্রে এটি লক্ষণীয় নয়। যাইহোক, আপনি যদি কোনও অভ্যন্তরীণ লুপের মধ্যে বক্সিং বা আনবক্সিং সম্পাদন করতে থাকেন তবে আপনি দেখতে পাবেন যে এটি সিপিইউ এবং আবর্জনা সংগ্রহের ওভারহেড চাপিয়ে দিতে পারে।
স্ট্রিমস এপিআই ডিজাইন করার সময় এটি স্পষ্ট ছিল যে আমাদের আদিমদের সমর্থন করতে হয়েছিল। বক্সিং / আনবক্সিং ওভারহেড সমান্তরালতা থেকে কোনও কার্যকারিতা সুবিধা হারাতে পারে। আমরা সমস্ত আদিম মানুষকে সমর্থন করতে চাইনি , যদিও এপিআইতে বিপুল পরিমাণে বিশৃঙ্খলা যুক্ত হত। (আপনি কি সত্যই এর ব্যবহার দেখতে পাচ্ছেন ShortStream
?) "সমস্ত" বা "কোনওটিই" ডিজাইনের জন্য আরামদায়ক জায়গা, তবুও উভয়ই গ্রহণযোগ্য ছিল না। সুতরাং আমাদের "কিছু" এর একটি যুক্তিসঙ্গত মান খুঁজে পেতে হয়েছিল। আমরা আদিম বিশেষায়িত সঙ্গে শেষ পর্যন্ত int
, long
এবং double
। (ব্যক্তিগতভাবে আমি বাদ পড়তে পারতাম int
তবে এটি কেবল আমি।)
যেহেতু CharSequence.chars()
আমরা প্রত্যাবর্তন বিবেচনা করেছি Stream<Character>
(প্রথম দিকে প্রোটোটাইপ এটি প্রয়োগ করতে পারে) তবে বক্সিং ওভারহেডের কারণে এটি প্রত্যাখ্যান করা হয়েছিল। একটি স্ট্রিং রয়েছে তা বিবেচনা করেchar
স্ট্রিংয়ের আদিম হিসাবে মান করে, কলারটি শর্তহীনভাবে বক্সিং চাপিয়ে দেওয়া ভুল বলে মনে হবে যখন কলার সম্ভবত কেবলমাত্র মানটির উপর কিছুটা প্রসেসিং করবে এবং এটি ডানদিকে ফিরিয়ে আনবে।
আমরা একটি CharStream
আদিম বিশেষীকরণ হিসাবে বিবেচনা করেছি , তবে এটিআইপিতে যে পরিমাণ বাল্ক যোগ করবে তার তুলনায় এর ব্যবহার বেশ সংকীর্ণ বলে মনে হচ্ছে। এটি যুক্ত করা সার্থক বলে মনে হয় নি।
কলকারীদের উপর এই শাস্তি চাপিয়ে দেয় তা হ'ল তাদের জানতে হবে যে উপস্থাপিত হিসাবে মানগুলি IntStream
রয়েছে এবং কাস্টিং অবশ্যই যথাযথ জায়গায় করা উচিত। এটি দ্বিগুণ বিভ্রান্তিকর কারণ এখানে ওভারলোড হওয়া এপিআই কলগুলি রয়েছে এবং এটি তাদের আচরণে স্পষ্টতই পৃথক। বিভ্রান্তির একটি অতিরিক্ত পয়েন্ট সম্ভবত উত্থাপিত হয়েছে কারণ কলটি একটি ফেরত দেয় তবে এতে থাকা মানগুলি একেবারেই আলাদা।char
ints
PrintStream.print(char)
PrintStream.print(int)
codePoints()
IntStream
সুতরাং, বেশ কয়েকটি বিকল্পের মধ্যে এটি ব্যবহারিকভাবে বেছে নেওয়ার জন্য উত্সাহিত হয়:
আমরা কোনও আদিম বিশেষত্ব সরবরাহ করতে পারি না, যার ফলে একটি সাধারণ, মার্জিত, ধারাবাহিক এপিআই হয়, তবে এটি একটি উচ্চ কার্যকারিতা এবং জিসি ওভারহেড চাপিয়ে দেয়;
আমরা জেডিকে বিকাশকারীদের উপর রক্ষণাবেক্ষণের বোঝা চাপিয়ে, এপিআই খাড়া করার ব্যয়ে, আদিম বিশেষজ্ঞের একটি সম্পূর্ণ সেট সরবরাহ করতে পারি; অথবা
আমরা একটি মাঝারি আকারের, উচ্চ সম্পাদনকারী এপিআই প্রদান করে যে আঞ্চলিক আকারের সংক্ষিপ্ত ব্যবহারের ক্ষেত্রে (চর প্রক্রিয়াজাতকরণ) কলকারীদের উপর তুলনামূলকভাবে ছোট বোঝা চাপিয়ে আদিম বিশেষত্বের একটি উপসেট সরবরাহ করতে পারি।
আমরা শেষটি বেছে নিয়েছি।
chars()
, একটি যা Stream<Character>
(ছোট পারফরম্যান্সের জরিমানা সহ) প্রদান করে এবং অন্যটি IntStream
, এটিও বিবেচনা করা হয়েছিল? Stream<Character>
পারফরম্যান্স পেনাল্টির তুলনায় যদি বিশ্বাসযোগ্যতা এটির জন্য উপযুক্ত বলে মনে হয় তবে লোকেরা যে কোনও উপায়ে এটির ম্যাপিং শেষ করবে এটি সম্ভবত যথেষ্ট is
chars()
পদ্ধতি রয়েছে যা IntStream
একটিতে চর মানগুলি প্রদান করে তবে এটিতে অন্য একটি এপিআই কল আসবে না যা একই মানগুলি পাবে তবে বাক্স আকারে। কলার অনেক ঝামেলা ছাড়াই মানগুলি বাক্স করতে পারেন। নিশ্চিত যে এটি (সম্ভবত বিরল) ক্ষেত্রে এটি না করা আরও সুবিধাজনক হবে তবে এপিআইতে গোলমাল যোগ করার ব্যয়ে।
chars()
ফিরিয়ে IntStream
দেওয়া বড় সমস্যা নয়। তবে এটি একটি বিল্ট-ইন ভাবে ফিরে রূপান্তর আছে ভাল হবে IntStream
থেকে String
। এটি দিয়ে করা যেতে পারে .reduce(StringBuilder::new, (sb, c) -> sb.append((char)c), StringBuilder::append).toString()
, তবে এটি সত্যই দীর্ঘ।
collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString()
। আমার ধারণা এটি সত্যিই খাটো নয়, তবে কোড পয়েন্টগুলি ব্যবহার করা (char)
কাস্টগুলি এড়িয়ে যায় এবং পদ্ধতি রেফারেন্সগুলি ব্যবহারের অনুমতি দেয়। এছাড়াও এটি surrogates সঠিকভাবে পরিচালনা করে।
IntStream
কোনও collect()
পদ্ধতি গ্রহণ করে না Collector
। collect()
পূর্ববর্তী মন্তব্যে উল্লিখিত তাদের কাছে কেবল তিন-আর্গ পদ্ধতি রয়েছে।
CharStream
না থাকে তবে এটিকে যুক্ত করতে সমস্যা কী হবে?