জাভা 8 Iterable.forEach () বনাম ফোরচ লুপ


463

নীচের কোনটি জাভা 8 এ আরও ভাল অনুশীলন হয়?

জাভা 8:

joins.forEach(join -> mIrc.join(mSession, join));

জাভা 7:

for (String join : joins) {
    mIrc.join(mSession, join);
}

আমার কাছে প্রচুর লুপের জন্য রয়েছে যা ল্যাম্বডাস দিয়ে "সরলীকৃত" হতে পারে, তবে সেগুলি ব্যবহার করার কি আসলেই কোনও সুবিধা আছে? এটি তাদের কর্মক্ষমতা এবং পাঠযোগ্যতার উন্নতি করবে?

সম্পাদনা

আমি আরও দীর্ঘ পদ্ধতিতে এই প্রশ্নটি প্রসারিত করব। আমি জানি যে আপনি কোনও ল্যাম্বডা থেকে পিতামাতার ফাংশনটি ফিরে আসতে বা ভাঙ্গতে পারবেন না এবং তাদের তুলনা করার সময় এটিও বিবেচনা করা উচিত, তবে অন্য কিছু বিবেচনার জন্য কি?


10
একে অপরের আসল পারফরম্যান্সের সুবিধা নেই। প্রথম বিকল্পটি এফপি দ্বারা অনুপ্রাণিত কিছু (হুইচ সাধারণত আপনার কোড প্রকাশের জন্য আরও "দুর্দান্ত" এবং "পরিষ্কার" উপায়ের মতো কথা বলা হয়)। বাস্তবে - এটি বরং "শৈলী" প্রশ্ন।
ইউজিন লয়

5
@ ডব্লিউবি: এই ক্ষেত্রে, এটি প্রাসঙ্গিক নয়। জন্য প্রতিটি সমান্তরাল বা এর মতো কিছু হিসাবে সংজ্ঞায়িত করা হয় না, সুতরাং এই দুটি জিনিস শব্দার্থগতভাবে সমতুল্য। অবশ্যই forEach এর সমান্তরাল সংস্করণটি প্রয়োগ করা সম্ভব (এবং এটি একটি ইতিমধ্যে স্ট্যান্ডার্ড লাইব্রেরিতে উপস্থিত থাকতে পারে), এবং এই ক্ষেত্রে ল্যাম্বডা এক্সপ্রেশন সিনট্যাক্সটি খুব কার্যকর হবে।
আর্দ্বার্কসৌপ

8
@আর্ডওয়ার্কসৌপ উদাহরণস্বরূপ, যার জন্য ফরইচ বলা হয় সেটিকে স্ট্রিম বলা হয় ( ল্যাম্বডডোকটনেট / এপি / জাভা / ইউটিল / স্ট্রিম / স্ট্রিম এইচটিএমএল )। সমান্তরাল মৃত্যুদণ্ডের জন্য অনুরোধ করতে কেউ লিখতে পারত jains.pa Parall ()। ForEach (...)
mschenk74

13
joins.forEach((join) -> mIrc.join(mSession, join));আসলেই কি এর "সরলীকরণ" for (String join : joins) { mIrc.join(mSession, join); }? প্রকারের আড়াল করার সুবিধার জন্য আপনি বিরামচিহ্ন গণনা 9 থেকে 12 থেকে বাড়িয়েছেন join। আপনি যা করেছেন তা হ'ল দুটি লাইনে একটি লাইনে রেখে দেওয়া।
টম হাটিন -

7
আর একটি বিষয় বিবেচনার জন্য জাভা সীমিত পরিবর্তনশীল ক্যাপচার ক্ষমতা। স্ট্রিম.ফোরেচ () এর সাহায্যে, আপনি স্থানীয় পরিবর্তনগুলি আপডেট করতে পারবেন না কারণ তাদের ক্যাপচার তাদের চূড়ান্ত করে তোলে, যার অর্থ আপনি ফর ইচ ল্যাম্বডায় রাষ্ট্রীয় আচরণ করতে পারেন (যদি না আপনি শ্রেণীর রাষ্ট্রের ভেরিয়েবলগুলি ব্যবহার করার মতো কিছু কদর্যতার জন্য প্রস্তুত না হন)।
রেডগ্লাইফ

উত্তর:


509

আরও ভাল অনুশীলন ব্যবহার করা হয় for-eachকীপ ইট সিম্পল, বোকা নীতি লঙ্ঘন করা ছাড়াও , নতুন-রূপকথার forEach()কমপক্ষে নিম্নলিখিত কমতি রয়েছে:

  • চূড়ান্ত নয় এমন ভেরিয়েবলগুলি ব্যবহার করতে পারে না । সুতরাং, নীচের মতো কোডকে প্রতিটি ল্যাম্বডায় রূপান্তর করা যাবে না:

    Object prev = null;
    for(Object curr : list)
    {
        if( prev != null )
            foo(prev, curr);
        prev = curr;
    }
  • চেক করা ব্যতিক্রমগুলি পরিচালনা করতে পারে না । লাম্বডাসকে চেক করা ব্যতিক্রমগুলি ছুঁড়ে ফেলার জন্য আসলে নিষেধ করা হয় না, তবে সাধারণ ক্রিয়ামূলক ইন্টারফেসগুলি যেমন Consumerকোনও ঘোষণা না করে। অতএব, যে কোনও কোড যাচাই করা ব্যতিক্রম ছুঁড়ে ফেলেছে সেগুলি অবশ্যই এগুলিতে try-catchবা এঁকে রাখতে পারে Throwables.propagate()। তবে আপনি তা করলেও, ছুঁড়ে দেওয়া ব্যতিক্রমের কী হবে তা সর্বদা পরিষ্কার নয়। এটি সাহসের সাথে কোথাও গিলে যেতে পারেforEach()

  • সীমিত প্রবাহ-নিয়ন্ত্রণ । একটি returnএকটি ল্যামডা একটি সমান continueএকটি জন্য-প্রতিটি ক্ষেত্রে কিন্তু একটি কোন সমতূল্য break। রিটার্ন মান, শর্ট সার্কিট বা পতাকা সেট সেট করা যেমন কাজ করাও কঠিন (যেমন এটি চূড়ান্ত কোনও চূড়ান্ত নিয়মের লঙ্ঘন না হলে জিনিসগুলি কিছুটা । "এটি কেবলমাত্র একটি অপ্টিমাইজেশন নয়, তবে যখন আপনি বিবেচনা করেন যে কিছু সিকোয়েন্সগুলি (যেমন কোনও ফাইলের লাইনগুলি পড়া) এর পার্শ্ব-প্রতিক্রিয়া থাকতে পারে, বা আপনার অসীম অনুক্রম হতে পারে।"

  • সমান্তরালভাবে নির্বাহ করা হতে পারে , যা আপনার কোডের 0.1% ছাড়াও অপরিহার্য হওয়া দরকার, যা সকলের জন্য একটি ভয়ঙ্কর, ভয়াবহ জিনিস। যে কোনও সমান্তরাল কোডের মাধ্যমে ভাবতে হবে (এমনকি যদি এটি লকস, অস্থিরতা এবং traditionalতিহ্যবাহী মাল্টি-থ্রেডড এক্সিকিউশনের অন্যান্য বিশেষত বাজে দিকগুলি ব্যবহার করে না)। যে কোনও বাগ খুঁজে পাওয়া শক্ত হবে।

  • আঘাতের পারফরম্যান্স হতে পারেক্ষতিকারক , কারণ জেআইটি প্লে লুপগুলির সমানভাবে প্রতিটি () + ল্যাম্বডাকে অপ্টিমাইজ করতে পারে না, বিশেষত এখন ল্যাম্বডাস নতুন। "অপ্টিমাইজেশন" বলতে আমি ল্যাম্বডাস (যা ছোট) কল করার ওভারহেড বোঝায় না, তবে আধুনিক জেআইটি সংকলক চলমান কোডের জন্য পরিশীলিত বিশ্লেষণ এবং রূপান্তরকে বোঝায়।

  • আপনার যদি সমান্তরালতা প্রয়োজন হয় তবে এটি সম্ভবত খুব দ্রুত এবং এক্সিকিউটর সার্ভিস ব্যবহার করা আরও বেশি কঠিন নয় । স্ট্রিমগুলি উভয়ই অটোমেজিকাল (পড়ুন: আপনার সমস্যার সম্পর্কে খুব বেশি জানেন না) এবং একটি বিশেষায়িত (পড়ুন: সাধারণ ক্ষেত্রে অকার্যকর) প্যারালালাইজেশন কৌশল ( কাঁটাচামচ যোগদানের পুনরাবৃত্তিক পচন ) ব্যবহার করুন।

  • ডিবাগিংকে আরও বিভ্রান্তিকর করে তোলেনেস্টেড কল ক্রিয়াকলাপের কারণে এবং , godশ্বর বারণ করেন না, সমান্তরাল মৃত্যুদন্ড কার্যকর করেন। ডিবাগারে আশেপাশের কোডগুলি থেকে ভেরিয়েবলগুলি প্রদর্শনের সমস্যা থাকতে পারে এবং স্টেপ-থ্রো-এর মতো জিনিসগুলি প্রত্যাশার মতো কাজ করতে পারে না।

  • সাধারণভাবে স্ট্রীমগুলি কোড করা, পড়া এবং ডিবাগ করা আরও কঠিন । আসলে, এটি জটিল সত্য " সাধারণভাবে সাবলীল " এপিআইগুলির ক্ষেত্রে । জটিল একক বিবৃতিগুলির সংমিশ্রণ, জেনেরিকের ভারী ব্যবহার এবং মধ্যবর্তী ভেরিয়েবলের অভাব বিভ্রান্তিকর ত্রুটি বার্তা উত্পন্ন করার এবং ডিবাগিং হতাশ করার ষড়যন্ত্র করে। "এই ধরণের এক্স প্রকারের জন্য কোনও ওভারলোড নেই" এর পরিবর্তে আপনি "কোথাও আপনি প্রকারগুলি গুছিয়ে নিয়েছেন, কিন্তু কোথায় বা কীভাবে হয়" আমরা জানি না " একইভাবে, আপনি কোডটি একাধিক স্টেটমেন্টে বিভক্ত হয়ে যাওয়ার সময় সহজেই কোনও ডিবাগারের মধ্যে পদক্ষেপ এবং পরীক্ষা করতে পারবেন না এবং মধ্যবর্তী মানগুলি ভেরিয়েবলগুলিতে সংরক্ষণ করা হয়। শেষ অবধি, কোডটি পড়া এবং মৃত্যুদন্ডের প্রতিটি পর্যায়ে প্রকারগুলি এবং আচরণগুলি বোঝা অপ্রয়োজনীয় হতে পারে।

  • বুড়ো আঙুলের মতো লাঠি ফেলে । জাভা ভাষার ইতিমধ্যে প্রতিটি বিবৃতি রয়েছে। কেন এটি একটি ফাংশন কল দিয়ে প্রতিস্থাপন করবেন? কোথাও প্রকাশের কারণে পার্শ্ব-প্রতিক্রিয়াগুলি লুকিয়ে রাখতে উত্সাহিত করবেন? কেন অযৌক্তিক ওয়ান-লাইনারগুলিকে উত্সাহিত করবেন? প্রত্যেকের জন্য নিয়মিত এবং নতুন প্রতিটি উইলির জন্য মিক্স করা খারাপ স্টাইল bad কোডটি আইডিয়ামগুলিতে কথা বলা উচিত (নিদর্শনগুলি যা তাদের পুনরাবৃত্তির কারণে দ্রুত বুঝতে পারা যায়), এবং কোডগুলি যত কম পরিচ্ছন্নভাবে ব্যবহৃত হয় তা ব্যবহার করা হয় এবং কোন আইডিয়মটি ব্যবহার করা উচিত তা সিদ্ধান্ত নেওয়ার ক্ষেত্রে কম সময় ব্যয় করা হয় (আমার মতো পারফেকশনিস্টদের জন্য একটি বড় সময়-ড্রেন! )।

যেমন আপনি দেখতে পাচ্ছেন, আমি যখন বোধগম্য হন তখন ব্যতীত আমি প্রত্যেকের () ফলের খুব বেশি অনুরাগী নই।

বিশেষত আমার কাছে আপত্তিজনক ঘটনাটি Streamবাস্তবায়িত হয় না Iterable(বাস্তবে পদ্ধতি থাকা সত্ত্বেও iterator) এবং কেবলমাত্র একটি ফর (প্রতিটি) দিয়ে প্রতিটির জন্য ব্যবহার করা যায় না। আমি এর সাথে আইটেমারেবল স্ট্রিমগুলি কাস্ট করার পরামর্শ দিচ্ছি (Iterable<T>)stream::iterator। আরও ভাল বিকল্প স্ট্রিমেক্স ব্যবহার করা যা বাস্তবায়ন সহ স্ট্রিম এপিআই সমস্যাগুলির বেশ কয়েকটি সমাধান করে Iterable

যা বলেছিল, forEach()নিম্নলিখিতগুলির জন্য দরকারী:

  • একটি সিঙ্ক্রোনাইজ করা তালিকার উপরে পারমাণবিকভাবে পুনরাবৃত্তি । এর আগে, তৈরি হওয়া তালিকাটি Collections.synchronizedList()পেতে বা সেট করার মতো জিনিসের ক্ষেত্রে পারমাণবিক ছিল, তবে পুনরাবৃত্তির সময় থ্রেড-নিরাপদ ছিল না।

  • সমান্তরাল সম্পাদন (উপযুক্ত সমান্তরাল স্ট্রিম ব্যবহার করে) । যদি আপনার সমস্যা স্ট্রিম এবং স্প্লিটেটরগুলির মধ্যে নির্মিত পারফরম্যান্স অনুমানের সাথে মেলে তবে এটি একটি এক্সিকিউটর সার্ভিস ব্যবহার করে আপনার বনাম কয়েকটি লাইনের কোড সংরক্ষণ করে।

  • নির্দিষ্ট পাত্রে যা সিঙ্ক্রোনাইজ করা তালিকার মতো পুনরাবৃত্তির নিয়ন্ত্রণে থাকার ফলে উপকৃত হয় (যদিও এটি বেশিরভাগ ক্ষেত্রে তাত্ত্বিক হয় যদি না লোকেরা আরও উদাহরণ আনতে পারে)

  • কোনও একক ফাংশনটিকে আরও পরিষ্কার করে কল করে forEach()একটি পদ্ধতি রেফারেন্স আর্গুমেন্ট (অর্থাত্ list.forEach (obj::someMethod))। তবে, চেক করা ব্যতিক্রম, আরও বেশি জটিল ডিবাগিং এবং কোড লেখার সময় আপনি যে আইডিয়মের ব্যবহার করছেন তা হ্রাস করার পয়েন্টগুলি মনে রাখবেন।

আমি নিবন্ধগুলি রেফারেন্সের জন্য ব্যবহার করেছি:

সম্পাদনা: মনে হচ্ছে ল্যাম্বডাসের জন্য কিছু মূল প্রস্তাব (যেমন http://www.javac.info/closures-v06a.html ) আমার উল্লেখ করা কিছু সমস্যা সমাধান করেছে (অবশ্যই তাদের নিজস্ব জটিলতা যুক্ত করার সময়)।


95
"কেন প্রকাশের কারণে কোথাও পার্শ্ব-প্রতিক্রিয়া লুকিয়ে রাখতে উত্সাহিত করবেন?" ভুল প্রশ্ন। কার্যকরী forEachসেখানে কার্যকরী শৈলী উত্সাহ দেয়, অর্থাত্ পার্শ্ব প্রতিক্রিয়া ছাড়াই এক্সপ্রেশন ব্যবহার করে । আপনি যদি পরিস্থিতির মুখোমুখি হন তবে forEachআপনার পার্শ্ব প্রতিক্রিয়াগুলির সাথে ভাল কাজ করে না আপনার অনুভূতি হওয়া উচিত যে আপনি কাজের জন্য সঠিক সরঞ্জামটি ব্যবহার করছেন না। তারপরে সহজ উত্তরটি হ'ল, কারণ আপনার অনুভূতিটি সঠিক so তাই এর জন্য প্রতিটি লুপে থাকুন। ধ্রুপদী forলুপটি অবচয় করা হয়নি ...
হোলার

17
@ হোলজার কীভাবে forEachপার্শ্ব প্রতিক্রিয়া ছাড়াই ব্যবহার করা যেতে পারে?
আলেকসান্দ্র ডাবিনস্কি

14
ঠিক আছে, আমি যথেষ্ট সুনির্দিষ্ট ছিলাম না, forEachপার্শ্ব-প্রতিক্রিয়াগুলির উদ্দেশ্যে কেবলমাত্র স্ট্রিম অপারেশন, তবে এটি আপনার উদাহরণ কোডের মতো পার্শ্ব-প্রতিক্রিয়ার জন্য নয়, গণনা একটি সাধারণ reduceক্রিয়াকলাপ। আমি স্টাম্পের নিয়ম হিসাবে, প্রতিটি অপারেশন যা স্থানীয় ভেরিয়েবলগুলি পরিচালনা করে বা ক্লাসিকাল forলুপে নিয়ন্ত্রণ প্রবাহকে (Incl ব্যতিক্রম হ্যান্ডলিং) প্রভাবিত করবে তা রাখার পরামর্শ দেব । আমি মনে করি মূল প্রশ্নটি সম্পর্কে, সমস্যাটি এমনটি থেকে উদ্ভূত হয়েছিল যে কেউ স্ট্রিম ব্যবহার করে যেখানে প্রবাহের forউত্সের উপর একটি সরল লুপ যথেষ্ট would forEach()কেবলমাত্র কাজ করে এমন স্ট্রিম ব্যবহার করুন
হলগার

8
@ হোলজার পার্শ্বপ্রতিক্রিয়ার একটি উদাহরণ যা forEachউপযুক্ত?
আলেকসান্দ্র ডাবিনস্কি

29
এমন কিছু যা প্রতিটি আইটেমকে স্বতন্ত্রভাবে প্রক্রিয়া করে এবং স্থানীয় ভেরিয়েবলগুলিকে পরিবর্তনের চেষ্টা করে না। উদাহরণস্বরূপ আইটেমগুলিকে নিজেরাই পরিচালনা করা বা সেগুলি মুদ্রণ করা, কোনও ফাইল, নেটওয়ার্ক স্ট্রিম ইত্যাদিতে লিখিত / প্রেরণ ইত্যাদি; যদি আপনি এই উদাহরণগুলি নিয়ে প্রশ্ন করেন এবং এর জন্য কোনও অ্যাপ্লিকেশন না দেখেন তবে আমার পক্ষে সমস্যা নেই; ফিল্টারিং, ম্যাপিং, হ্রাস, অনুসন্ধান এবং (কম পরিমাণে) সংগ্রহ করা একটি স্রোতের পছন্দের ক্রিয়াকলাপ। ফোরএইচটি বিদ্যমান এপিআইগুলির সাথে লিঙ্ক করার জন্য আমার কাছে সুবিধার মতো মনে হচ্ছে। এবং সমান্তরাল অপারেশন জন্য অবশ্যই। এগুলি forলুপগুলির সাথে কাজ করবে না ।
হলগার

169

সমান্তরালভাবে অপারেশনগুলি কার্যকর করা যেতে পারে যখন সুবিধাটি অ্যাকাউন্টে আসে। (দেখুন http://java.dzone.com/articles/devoxx-2012-java-8-lambda- এবং - অভ্যন্তরীণ এবং বাহ্যিক পুনরাবৃত্তি সম্পর্কে বিভাগ)

  • আমার দৃষ্টিকোণ থেকে মূল সুবিধাটি হ'ল লুপের মধ্যে যা করতে হবে তা বাস্তবায়ন সমান্তরাল বা অনুক্রমিকভাবে কার্যকর করা হবে কিনা তা সিদ্ধান্ত না নিয়েই সংজ্ঞায়িত করা যায়

  • আপনি যদি চান যে আপনার লুপটি সমান্তরালে কার্যকর করা যায় তবে আপনি কেবল লিখতে পারেন

     joins.parallelStream().forEach(join -> mIrc.join(mSession, join));

    থ্রেড হ্যান্ডলিং ইত্যাদির জন্য আপনাকে কিছু অতিরিক্ত কোড লিখতে হবে

দ্রষ্টব্য: আমার উত্তরের জন্য আমি ধরে নিয়েছি java.util.Streamইন্টারফেসটি প্রয়োগের সাথে যোগ দেয় । যদি কেবল java.util.Iterableইন্টারফেস প্রয়োগ করে তবে এটি আর সত্য নয়।


4
তিনি যে ওরাকল ইঞ্জিনিয়ারের উল্লেখ করছেন ( স্লোগানগুলি। ব্লগস.অরাকলস / ডারসি / রিসোর্স / ডেভোএক্সএক্স / )) সেই ল্যাম্বডা এক্সপ্রেশনগুলির মধ্যে সমান্তরালতার কথা উল্লেখ করে না। সমান্তরালতা যেমন বাল্ক সংগ্রহের পদ্ধতির মধ্যে দেখা যায় mapএবং foldএটি ল্যাম্বডাসের সাথে সম্পর্কিত নয়।
থমাস জংবলুট

1
এটি সত্যই মনে হয় না যে ওপির কোডটি এখানে স্বয়ংক্রিয় সমান্তরালতা থেকে উপকৃত হবে (বিশেষত যেহেতু কোনও নিশ্চয়তার কোনও নিশ্চয়তা নেই)। আমরা আসলে "এমআরসি" কী তা জানি না, তবে "যোগদান" আসলে এমন কিছু বলে মনে হয় না যা আউট অফ-অর্ডার থেকে বেরিয়ে যায়।
ইউজিন লয়

10
Stream#forEachএবং Iterable#forEachএকই জিনিস নয়। ওপি সম্পর্কে জিজ্ঞাসা করা হয় Iterable#forEach
gvlasov

2
প্রশ্নটি জিজ্ঞাসা করার সময় এবং উত্তর আপডেট হওয়ার সময়ের মধ্যে স্পেসিফিকেশনের পরিবর্তন হওয়ার কারণে আমি ইউপিডিএটিএক্স শৈলী ব্যবহার করেছি। উত্তরের ইতিহাস ছাড়া এটি আরও বিভ্রান্তিকর হবে বলে আমি ভেবেছিলাম।
mschenk74

1
কেউ দয়া করে আমাকে ব্যাখ্যা করতে পারেন joinsযে Iterableপরিবর্তে পরিবর্তিত হলে এই উত্তরটি কেন বৈধ নয় Stream? আমি যে কয়েকটি জিনিস পড়েছি সেগুলি থেকে, ওপি করতে সক্ষম হবে joins.stream().forEach((join) -> mIrc.join(mSession, join));এবং joins.parallelStream().forEach((join) -> mIrc.join(mSession, join));যদি joinsপ্রয়োগ হয়Iterable
ব্লুভারটি

112

এই প্রশ্নটি পড়ার সময় যে কেউ বুঝতে পারে যে Iterable#forEachল্যাম্বডা এক্সপ্রেশনগুলির সাথে একত্রে প্রতিটি লুপকে লেখার জন্য একটি শর্টকাট / প্রতিস্থাপন। এই কেবল সত্য নয়। ওপি থেকে এই কোড:

joins.forEach(join -> mIrc.join(mSession, join));

হয় না লেখার জন্য একটি শর্টকাট হিসাবে উদ্দীষ্ট

for (String join : joins) {
    mIrc.join(mSession, join);
}

এবং অবশ্যই এইভাবে ব্যবহার করা উচিত নয়। (যদিও এটা পরিবর্তে এটি একটি শর্টকাট হিসাবে দেয়ার উদ্দেশ্যে করা হচ্ছে না লেখার জন্য ঠিক একই)

joins.forEach(new Consumer<T>() {
    @Override
    public void accept(T join) {
        mIrc.join(mSession, join);
    }
});

এবং এটি নিম্নলিখিত জাভা 7 কোডের প্রতিস্থাপন হিসাবে রয়েছে:

final Consumer<T> c = new Consumer<T>() {
    @Override
    public void accept(T join) {
        mIrc.join(mSession, join);
    }
};
for (T t : joins) {
    c.accept(t);
}

উপরের উদাহরণগুলির মতো একটি লুপের বডিটি একটি কার্যকরী ইন্টারফেসের সাথে প্রতিস্থাপন করা আপনার কোডটিকে আরও সুস্পষ্ট করে তোলে: আপনি বলছেন যে (1) লুপটির শরীরটি আশেপাশের কোড এবং নিয়ন্ত্রণের প্রবাহকে প্রভাবিত করে না এবং (২) লুপের বডিটি পার্শ্ববর্তী কোডকে প্রভাবিত না করে ফাংশনটির ভিন্ন প্রয়োগের সাথে প্রতিস্থাপন করা যেতে পারে। বাহ্যিক স্কোপের অ চূড়ান্ত ভেরিয়েবল অ্যাক্সেস করতে না পারা ফাংশন / ল্যাম্বডাসের ঘাটতি নয়, এটি প্রতিটি বৈশিষ্ট্যেরIterable#forEach জন্য প্রতিটি লুপের শব্দার্থক শব্দার্থ থেকে শব্দার্থকে আলাদা করে তোলে feature একবারের সিন্টেক্সে অভ্যস্ত হয়ে যায়Iterable#forEach এটি কোডটিকে আরও পঠনযোগ্য করে তোলে, কারণ আপনি তত্ক্ষণাত কোড সম্পর্কে এই অতিরিক্ত তথ্য পেয়ে যান।

Loতিহ্যবাহী জন্য প্রতিটি লুপগুলি জাভাতে অবশ্যই ভাল অনুশীলন করবে (অতিরিক্ত ব্যবহৃত শব্দ " সেরা অনুশীলন " এড়ানোর জন্য )। তবে এর অর্থ এই নয় যে Iterable#forEachএটিকে খারাপ অনুশীলন বা খারাপ শৈলী হিসাবে বিবেচনা করা উচিত। কাজটি করার জন্য সঠিক সরঞ্জামটি ব্যবহার করা সর্বদা ভাল অনুশীলন, এবং এর মধ্যে প্রতিটি লুপের সাথে traditionalতিহ্যবাহী মিশ্রণ অন্তর্ভুক্ত রয়েছে Iterable#forEach, যেখানে এটি বোধগম্য হয়।

যেহেতু ডাউনসাইডগুলি Iterable#forEachইতিমধ্যে এই থ্রেডে আলোচনা করা হয়েছে, তাই এখানে কিছু কারণ রয়েছে যা আপনি সম্ভবত ব্যবহার করতে চাইতে পারেন Iterable#forEach:

  • আপনার কোডটি আরও সুস্পষ্ট করতে: উপরে বর্ণিত হিসাবে, কিছু পরিস্থিতিতে আপনার কোডটিকে আরও স্পষ্ট এবং পঠনযোগ্য করে তুলতে Iterable#forEach পারে

  • আপনার কোডটিকে আরও বর্ধনযোগ্য এবং রক্ষণাবেক্ষণযোগ্য করে তুলতে: একটি লুপের মূল অংশ হিসাবে কোনও ফাংশন ব্যবহার করা আপনাকে এই কার্যকারিতাটি বিভিন্ন বাস্তবায়নের সাথে প্রতিস্থাপন করতে দেয় ( কৌশল প্যাটার্ন দেখুন )। আপনি উদাহরণস্বরূপ ল্যাম্বডা এক্সপ্রেশনটি সহজেই কোনও মেথড কলের সাথে প্রতিস্থাপন করতে পারেন যা উপ-শ্রেণীর দ্বারা ওভাররাইট করা যেতে পারে:

    joins.forEach(getJoinStrategy());

    তারপরে আপনি এনাম ব্যবহার করে ডিফল্ট কৌশল সরবরাহ করতে পারেন যা কার্যকরী ইন্টারফেস প্রয়োগ করে। এটি কেবল আপনার কোডকে আরও প্রসারিত করে না, এটি রক্ষণাবেক্ষণকেও বাড়ায় কারণ এটি লুপ ঘোষণার মাধ্যমে লুপ বাস্তবায়নকে ডুপ্পল করে।

  • আপনার কোডটি আরও ডিবাজিযোগ্য করার জন্য: ঘোষণা থেকে লুপ প্রয়োগ পৃথক করা ডিবাগিংকে আরও সহজ করে তুলতে পারে, কারণ আপনার একটি বিশেষ ডিবাগ বাস্তবায়ন হতে পারে, যা আপনার মূল কোডটি বিশৃঙ্খলা না করেই ডিবাগ বার্তাগুলি মুদ্রণ করে if(DEBUG)System.out.println()। ডিবাগ বাস্তবায়ন যেমন একটি প্রতিনিধি হতে পারে , যা প্রকৃত ফাংশন বাস্তবায়ন সজ্জিত করে।

  • অপ্টিমাইজ কর্মক্ষমতা-সমালোচনামূলক কোড করার জন্য: গবেষকেরা কিছু বিপরীত এই থ্রেড, Iterable#forEach নেই ইতিমধ্যে চেয়ে ভাল কর্মক্ষমতা একটি ঐতিহ্যগত জন্য-প্রতিটি লুপ, অন্তত ArrayList ব্যবহার করে এবং "-client" মোডে হটস্পট চলমান হয়। যদিও বেশিরভাগ ব্যবহারের ক্ষেত্রে এই পারফরম্যান্স উত্সাহটি ছোট এবং তুচ্ছ, তবে এমন কিছু পরিস্থিতি রয়েছে যেখানে এই অতিরিক্ত কর্মক্ষমতা একটি পার্থক্য আনতে পারে। উদাহরণস্বরূপ গ্রন্থাগারের রক্ষণাবেক্ষণকারীরা অবশ্যই তাদের কিছু বিদ্যমান লুপ বাস্তবায়ন যদি প্রতিস্থাপন করে তবে তা মূল্যায়ন করতে চাইবে Iterable#forEach

    ঘটনা সঙ্গে এই বিবৃতি ব্যাক আপ করার জন্য, আমি সঙ্গে কিছু মাইক্রো- benchmarks করেছ ক্যালিপার । এখানে পরীক্ষার কোডটি দেওয়া হয়েছে (গিট থেকে সর্বশেষ ক্যালিপার প্রয়োজন):

    @VmOptions("-server")
    public class Java8IterationBenchmarks {
    
        public static class TestObject {
            public int result;
        }
    
        public @Param({"100", "10000"}) int elementCount;
    
        ArrayList<TestObject> list;
        TestObject[] array;
    
        @BeforeExperiment
        public void setup(){
            list = new ArrayList<>(elementCount);
            for (int i = 0; i < elementCount; i++) {
                list.add(new TestObject());
            }
            array = list.toArray(new TestObject[list.size()]);
        }
    
        @Benchmark
        public void timeTraditionalForEach(int reps){
            for (int i = 0; i < reps; i++) {
                for (TestObject t : list) {
                    t.result++;
                }
            }
            return;
        }
    
        @Benchmark
        public void timeForEachAnonymousClass(int reps){
            for (int i = 0; i < reps; i++) {
                list.forEach(new Consumer<TestObject>() {
                    @Override
                    public void accept(TestObject t) {
                        t.result++;
                    }
                });
            }
            return;
        }
    
        @Benchmark
        public void timeForEachLambda(int reps){
            for (int i = 0; i < reps; i++) {
                list.forEach(t -> t.result++);
            }
            return;
        }
    
        @Benchmark
        public void timeForEachOverArray(int reps){
            for (int i = 0; i < reps; i++) {
                for (TestObject t : array) {
                    t.result++;
                }
            }
        }
    }

    এবং ফলাফল এখানে:

    "-ক্লিয়েন্ট" দিয়ে চলার সময় একটি অ্যারেলিস্টের Iterable#forEachউপর লুপের জন্য গতানুগতিকতা ছাড়িয়ে যায় তবে সরাসরি অ্যারের উপরে পুনরাবৃত্তি করার চেয়ে ধীর হয়। "-সার্ভার" দিয়ে চলার সময়, সমস্ত পদ্ধতির পারফরম্যান্স প্রায় একই রকম।

  • সমান্তরাল সম্পাদনার জন্য supportচ্ছিক সমর্থন সরবরাহ করার জন্য: এটি ইতিমধ্যে এখানে বলা হয়েছে যে স্রোতগুলিIterable#forEach ব্যবহার করে সমান্তরালভাবে ফাংশনাল ইন্টারফেস কার্যকর করার সম্ভাবনা অবশ্যই একটি গুরুত্বপূর্ণ দিক। যেহেতু গ্যারান্টি দেয় না, লুপটি আসলে সমান্তরালে সম্পাদিত হয়, তাই একে অবশ্যই এটি একটি an চ্ছিক বৈশিষ্ট্য হিসাবে বিবেচনা করা উচিত । এর সাথে আপনার তালিকার উপরে পুনরাবৃত্তি করার মাধ্যমে আপনি স্পষ্টভাবে বলবেন: এই লুপটি সমর্থন করেCollection#parallelStream()list.parallelStream().forEach(...); সমান্তরাল করে তবে এটি এর উপর নির্ভর করে না। আবার, এটি একটি বৈশিষ্ট্য এবং ঘাটতি নয়!

    আপনার প্রকৃত লুপ বাস্তবায়ন থেকে দূরে সমান্তরাল সম্পাদনের সিদ্ধান্তটি সরিয়ে আপনি কোডটিকে নিজেরাই প্রভাবিত না করে আপনার কোডটির alচ্ছিক অপ্টিমাইজেশনের অনুমতি দিন, যা একটি ভাল জিনিস। এছাড়াও, যদি ডিফল্ট সমান্তরাল স্ট্রিম বাস্তবায়ন আপনার প্রয়োজনের সাথে খাপ খায় না, তবে আপনার নিজের বাস্তবায়ন সরবরাহ করতে কেউ আপনাকে বাধা দিচ্ছে না। আপনি উদাহরণস্বরূপ অন্তর্নিহিত অপারেটিং সিস্টেমের উপর নির্ভর করে সংগ্রহের আকারের উপর, কোরের সংখ্যার উপর এবং কিছু পছন্দসই সেটিংসের উপর নির্ভর করে একটি অনুকূলিতকরণ সংগ্রহ সরবরাহ করতে পারেন:

    public abstract class MyOptimizedCollection<E> implements Collection<E>{
        private enum OperatingSystem{
            LINUX, WINDOWS, ANDROID
        }
        private OperatingSystem operatingSystem = OperatingSystem.WINDOWS;
        private int numberOfCores = Runtime.getRuntime().availableProcessors();
        private Collection<E> delegate;
    
        @Override
        public Stream<E> parallelStream() {
            if (!System.getProperty("parallelSupport").equals("true")) {
                return this.delegate.stream();
            }
            switch (operatingSystem) {
                case WINDOWS:
                    if (numberOfCores > 3 && delegate.size() > 10000) {
                        return this.delegate.parallelStream();
                    }else{
                        return this.delegate.stream();
                    }
                case LINUX:
                    return SomeVerySpecialStreamImplementation.stream(this.delegate.spliterator());
                case ANDROID:
                default:
                    return this.delegate.stream();
            }
        }
    }

    এখানে দুর্দান্ত জিনিসটি হ'ল আপনার লুপ প্রয়োগের জন্য এই বিবরণগুলি সম্পর্কে জানা বা যত্নের প্রয়োজন নেই।


5
এই আলোচনায় আপনার একটি আকর্ষণীয় দৃষ্টিভঙ্গি রয়েছে এবং বেশ কয়েকটি বিষয় তুলে ধরেছেন। আমি তাদের সম্বোধন করার চেষ্টা করব। আপনি লুপের বডিটির প্রকৃতি সম্পর্কিত কিছু মানদণ্ডের মধ্যে forEachএবং এর মধ্যে স্যুইচ করার প্রস্তাব দেন for-each। এই জাতীয় নিয়মগুলি অনুসরণ করার জন্য বুদ্ধি এবং শৃঙ্খলা একটি ভাল প্রোগ্রামারের বৈশিষ্ট্য। এই জাতীয় নিয়মগুলিও তার নিষিদ্ধ, কারণ তার চারপাশের লোকেরা হয় তাদের অনুসরণ করে না বা একমত হয় না। উদাহরণস্বরূপ, চেক করা বনাম চেক করা ব্যতিক্রমগুলি ব্যবহার করে। এই পরিস্থিতি আরও সংবেদনশীল বলে মনে হয়। তবে, যদি শরীর "চারপাশের কোড বা প্রবাহ নিয়ন্ত্রণকে প্রভাবিত করে না," তবে এটি আরও কার্যকরভাবে কার্যকরী হিসাবে প্রমাণ করে না?
আলেকসান্দ্র ডাবিনস্কি

4
বিস্তারিত মন্তব্য আলেকজান্ডারের জন্য ধন্যবাদ। But, if the body "does not affect surround code or flow control," isn't factoring it out as a function better?। হ্যাঁ, প্রায়শই আমার মতে এটি হবে - ফাংশন হিসাবে এই লুপগুলি ফ্যাক্টর করা একটি প্রাকৃতিক পরিণতি।
বাল্ডার

2
পারফরম্যান্স ইস্যু সম্পর্কিত - আমার ধারণা এটি লুপের প্রকৃতির উপর খুব নির্ভর করে। যে প্রকল্পে আমি কাজ করছি, আমি Iterable#forEachজাভা 8 এর আগে একইভাবে ফাংশন-স্টাইলের লুপগুলি ব্যবহার করেছি কেবলমাত্র পারফরম্যান্স বৃদ্ধির কারণে। প্রশ্নে প্রকল্পটির একটি প্রধান লুপ একটি গেম লুপের মতো, নেস্টেড সাব-লুপগুলির একটি অপরিজ্ঞাত সংখ্যার সাথে রয়েছে, যেখানে ক্লায়েন্টরা লুপ অংশগ্রহণকারীদের ফাংশন হিসাবে প্লাগ-ইন করতে পারে। এই ধরনের একটি সফ্টওয়্যার কাঠামো থেকে ব্যাপকভাবে উপকৃত হয় Iteable#forEach
বাল্ডার

7
আমার সমালোচনার একেবারে শেষে একটি বাক্য রয়েছে: "কোডটি আইডিয়ামগুলিতে কথা বলা উচিত, এবং কোডগুলি যত কম পরিচ্ছন্ন হয় সেগুলি ব্যবহার করা উচিত এবং কোন আইডিয়মটি ব্যবহার করবেন তা সিদ্ধান্ত নেওয়ার ক্ষেত্রে কম সময় ব্যয় করা হয়"। আমি যখন সি # থেকে জাভাতে চলে এসেছিলাম তখন আমি এই বিষয়টির গভীরভাবে প্রশংসা করতে শুরু করি।
আলেকসান্দ্র ডাবিনস্কি

7
এটি একটি খারাপ যুক্তি। আপনি যা চান তা ন্যায়সঙ্গত করতে আপনি এটি ব্যবহার করতে পারেন: লুপের জন্য কেন আপনার ব্যবহার করা উচিত নয়, কারণ কিছুক্ষণের জন্য লুপটি যথেষ্ট ভাল এবং এটি হ'ল একটি কম বুদ্ধিমান। হেক, কেন কোনও লুপ ব্যবহার করুন, স্যুইচ করুন বা চেষ্টা করুন / ক্যাচ স্টেটমেন্টটি যখন গোটা সব কিছু করতে পারে।
তাপীচু

13

forEach()প্রতিটি লুপের চেয়ে দ্রুত হওয়ার জন্য প্রয়োগ করা যেতে পারে, কারণ পুনরাবৃত্তকারীরা তার উপাদানগুলিকে পুনরাবৃত্তি করার সর্বোত্তম উপায়টি জানেন, স্ট্যান্ডার্ড পুনরাবৃত্তির বিপরীতে। সুতরাং পার্থক্যটি অভ্যন্তরীণভাবে লুপ হয় বা বাহ্যিকভাবে লুপ হয়।

উদাহরণস্বরূপ ArrayList.forEach(action)সহজ হিসাবে বাস্তবায়ন করা যেতে পারে

for(int i=0; i<size; i++)
    action.accept(elements[i])

প্রতিটি লুপের বিপরীতে যার জন্য প্রচুর স্ক্যাফল্ডিং প্রয়োজন

Iterator iter = list.iterator();
while(iter.hasNext())
    Object next = iter.next();
    do something with `next`

তবে, আমাদের ব্যবহার করে দুটি ওভারহেড ব্যয়ের জন্য অ্যাকাউন্টিংও forEach()করতে হবে, একটি ল্যাম্বডা অবজেক্ট তৈরি করছে, অন্যটি ল্যাম্বডা পদ্ধতিটি চালাচ্ছে। এগুলি সম্ভবত উল্লেখযোগ্য নয় are

বিভিন্ন ব্যবহারের ক্ষেত্রে অভ্যন্তরীণ / বাহ্যিক পুনরাবৃত্তির তুলনা করার জন্য http: // j Journal.stuffwithstuff.com/2013/01/13/iteration-inside-and-out/ দেখুন ।


8
কেন পুনরাবৃত্তিযোগ্যরা সবচেয়ে ভাল উপায়ে জানেন তবে পুনরুক্তিকারী তা জানেন না?
mschenk74

2
কোনও প্রয়োজনীয় পার্থক্য নেই, তবে পুনরুক্তি ইন্টারফেসের সাথে সামঞ্জস্য করার জন্য অতিরিক্ত কোডের প্রয়োজন, যা আরও ব্যয়বহুল হতে পারে।
ঝং ইয়ু

1
@ zhong.j.yu যদি আপনি সংগ্রহটি বাস্তবায়ন করেন তবে আপনি যেভাবেই ইটারেবল প্রয়োগ করতে পারেন। সুতরাং, "মিসিং ইন্টারফেস পদ্ধতি প্রয়োগের জন্য আরও কোড যুক্ত করা" এর শর্তে কোনও কোড ওভারহেড নেই, যদি এটি আপনার বক্তব্য। যেমনটি এমএসচেঙ্ক said৪ বলেছে যে মনে হচ্ছে আপনি কেন আপনার সংগ্রহকে সবচেয়ে ভাল উপায়ে পুনরাবৃত্তি করতে পারেন তা জানতে আপনার পুনরাবৃত্তিকে টুইট করতে পারবেন না এমন কোনও কারণ নেই। আমি সম্মতি দিচ্ছি যে পুনরুক্তি তৈরির জন্য ওভারহেড থাকতে পারে তবে গম্ভীরভাবে, এই জিনিসগুলি সাধারণত এত সস্তা, আপনি বলতে পারেন যে তাদের শূন্যের দাম আছে ...
ইউজিন লয়

4
উদাহরণস্বরূপ কোনও গাছের void forEach(Consumer<T> v){leftTree.forEach(v);v.accept(rootElem);rightTree.forEach(v);}পুনরাবৃত্তি:, এটি বাহ্যিক পুনরাবৃত্তির চেয়ে আরও মার্জিত এবং আপনি কীভাবে সেরা সিঙ্ক্রোনাইজ করবেন সে বিষয়ে সিদ্ধান্ত নিতে পারেন
র‌্যাচেট ফ্রিক

1
মজাদারভাবে যথেষ্ট, String.joinপদ্ধতিগুলির মধ্যে একমাত্র মন্তব্য (ঠিক আছে, ভুল যোগ দেওয়া) হ'ল "অ্যারেগুলির মূল্যের উপযোগী সংখ্যক উপাদানগুলির সংখ্যা over" সুতরাং তারা লুপের জন্য একটি পশ ব্যবহার করে।
টম হাটিন -

7

টিএল; ডিআর : List.stream().forEach()দ্রুততম ছিল।

আমি অনুভব করেছি যে আমার ফলাফলগুলি বেঞ্চমার্কিং পুনরাবৃত্তি থেকে যুক্ত করা উচিত। আমি একটি খুব সহজ পদ্ধতির গ্রহণ করেছি (কোনও বেঞ্চমার্কিং ফ্রেমওয়ার্ক নেই) এবং 5 টি ভিন্ন পদ্ধতি বেঞ্চমার্ক করেছে:

  1. সর্বোত্তম for
  2. ক্লাসিক ভবিষ্যদ্বাণী
  3. List.forEach()
  4. List.stream().forEach()
  5. List.parallelStream().forEach

পরীক্ষা পদ্ধতি এবং পরামিতি

private List<Integer> list;
private final int size = 1_000_000;

public MyClass(){
    list = new ArrayList<>();
    Random rand = new Random();
    for (int i = 0; i < size; ++i) {
        list.add(rand.nextInt(size * 50));
    }    
}
private void doIt(Integer i) {
    i *= 2; //so it won't get JITed out
}

এই শ্রেণীর তালিকাটি পুনরাবৃত্তি হবে এবং কিছু কিছু doIt(Integer i)তার সদস্যদের জন্য প্রয়োগ করা হবে, প্রতিটি সময় আলাদা পদ্ধতির মাধ্যমে। মূল শ্রেণিতে আমি জেভিএম গরম করার জন্য পরীক্ষিত পদ্ধতিটি তিনবার চালিত করি। আমি তারপরে পরীক্ষার পদ্ধতিটি প্রতিটি পুনরাবৃত্তি পদ্ধতির জন্য (সময় ব্যবহারের System.nanoTime()) সময় লাগে এমন সমষ্টি 1000 বার চালায় । এটি শেষ হওয়ার পরে আমি সেই পরিমাণটি 1000 দ্বারা ভাগ করেছি এবং এটি ফলাফল, গড় সময়। উদাহরণ:

myClass.fored();
myClass.fored();
myClass.fored();
for (int i = 0; i < reps; ++i) {
    begin = System.nanoTime();
    myClass.fored();
    end = System.nanoTime();
    nanoSum += end - begin;
}
System.out.println(nanoSum / reps);

আমি এটি জাভা সংস্করণ 1.8.0_05 সহ একটি আই 5 4 কোর সিপিইউতে চালিত করেছি

সর্বোত্তম for

for(int i = 0, l = list.size(); i < l; ++i) {
    doIt(list.get(i));
}

এক্সিকিউশন সময়: 4.21 এমএস

ক্লাসিক ভবিষ্যদ্বাণী

for(Integer i : list) {
    doIt(i);
}

এক্সিকিউশন সময়: 5.95 এমএস

List.forEach()

list.forEach((i) -> doIt(i));

এক্সিকিউশন সময়: 3.11 এমএস

List.stream().forEach()

list.stream().forEach((i) -> doIt(i));

কার্যকর করার সময়: ২.79৯ এমএস

List.parallelStream().forEach

list.parallelStream().forEach((i) -> doIt(i));

এক্সিকিউশন সময়: 3.6 এমএস


23
আপনি কিভাবে এই নম্বর পেতে? আপনি কোন মাপদণ্ডের জন্য কাঠামো ব্যবহার করছেন? যদি আপনি System.out.printlnএই তথ্যটি নির্লজ্জভাবে প্রদর্শন করতে কোনও এবং কেবল প্লেইন ব্যবহার করেন না , তবে সমস্ত ফলাফল অকেজো।
লুইগি মেন্দোজা

2
কোনও কাঠামো নেই। আমি ব্যবহার System.nanoTime()। উত্তরটি পড়লে আপনি দেখতে পাবেন যে এটি কীভাবে হয়েছিল। আমি মনে করি না যে এটি একে অপ্রয়োজনীয় দেখায় কারণ এটি একটি আপেক্ষিক প্রশ্ন। কোনও নির্দিষ্ট পদ্ধতিটি কতটা ভাল করেছে তা আমার যত্ন নেই, অন্যান্য পদ্ধতির তুলনায় এটি কতটা ভাল করেছে তা আমি যত্নশীল care
আসফ

31
এবং এটি একটি ভাল মাইক্রো বেনমার্কের উদ্দেশ্য। যেহেতু আপনি এই জাতীয় প্রয়োজনীয়তা পূরণ করেন নি, ফলাফলগুলি অকেজো।
লুইগি মেন্দোজা

6
আমি পরিবর্তে জেএমএইচটি সম্পর্কে জানতে পরামর্শ দিতে পারি, এটি যা জাভা নিজেই ব্যবহার করা হচ্ছে এবং সঠিক সংখ্যাগুলি অর্জনের জন্য প্রচুর প্রচেষ্টা করে: openjdk.java.net/projects/code-tools/jmh
dsvensson

1
আমি @ লুইগি মেনডোজার সাথে একমত এই ফলাফলগুলি ধারাবাহিক বা বৈধ কিনা তা জানার কোনও উপায় নেই। Howশ্বর জানেন যে আমি কতগুলি মানদণ্ড করেছি যা বিভিন্ন ফলাফলের প্রতিবেদন রাখে, বিশেষত পুনরাবৃত্তির ক্রম, আকার এবং কী নয় depending
মিমি

6

আমি মনে করি আমার মন্তব্যটি কিছুটা বাড়িয়ে দেওয়া দরকার ...

দৃষ্টান্ত \ শৈলী সম্পর্কে

এটি সম্ভবত সবচেয়ে উল্লেখযোগ্য দিক। আপনি পার্শ্ব-প্রতিক্রিয়া এড়িয়ে যা পেতে পারেন তার কারণে এফপি জনপ্রিয় হয়ে উঠেছে। আপনি এগুলি থেকে কী লাভ করতে পারবেন তা আমি গভীরভাবে প্রকাশ করব না, কারণ এটি প্রশ্নের সাথে সম্পর্কিত নয়।

তবে আমি বলব যে Iterable.forEach ব্যবহার করে পুনরাবৃত্তিটি এফপি দ্বারা অনুপ্রাণিত হয়েছিল এবং জাভাতে আরও এফপি আনার ফলস্বরূপ (আমি বিস্মৃতভাবে বলতে চাই যে, খাঁটি এফপিতে ফরচেকের জন্য খুব বেশি কিছু নেই), কারণ এটি প্রবর্তন ছাড়া কিছুই করে না ক্ষতিকর দিক).

শেষ পর্যন্ত আমি বলব যে এটি বর্তমানে স্বাদ \ স্টাইল \ দৃষ্টান্তের বিষয় যা আপনি বর্তমানে লিখছেন।

সমান্তরালতা সম্পর্কে।

পারফরম্যান্সের দৃষ্টিকোণ থেকে Iterable.forEach ওভার ফরচ (...) ব্যবহার করে কোনও প্রতিশ্রুতিযুক্ত উল্লেখযোগ্য সুবিধা নেই।

Iterable.forEach এর সরকারী দস্তাবেজ অনুসারে :

সমস্ত উপাদান প্রক্রিয়াজাত না হওয়া বা ক্রিয়াটি একটি ব্যতিক্রম ছুঁড়ে না দেওয়া পর্যন্ত পুনরাবৃত্ত হওয়ার সময় ক্রম উপাদানগুলি ক্রম হিসাবে আইটেবলের সামগ্রীতে প্রদত্ত ক্রিয়া সম্পাদন করে ।

... অর্থাৎ দস্তাবেজগুলি আরও স্পষ্ট যে কোনও নিখুঁত সমান্তরালতা থাকবে না। একটি যুক্ত করা LSP লঙ্ঘন হবে।

এখন, জাভা 8-তে প্রতিশ্রুতি দেওয়া হয়েছে "সমান্তরাল সংগ্রহ" রয়েছে, তবে আমার সাথে আপনার আরও সুস্পষ্টভাবে প্রয়োজন এবং তাদের ব্যবহার করার জন্য কিছু অতিরিক্ত যত্ন রাখা (উদাহরণস্বরূপ mschenk74 এর উত্তর দেখুন) work

বিটিডাব্লু : এক্ষেত্রে স্ট্রিম.ফোর্চ প্রতিটি ব্যবহার করা হবে এবং এটি গ্যারান্টি দেয় না যে প্রকৃত কাজ সমান্তরালে করা হবে (অন্তর্নিহিত সংগ্রহের উপর নির্ভর করে)।

আপডেট: এটি এক নজরে স্পষ্ট এবং সামান্য প্রসারিত নাও হতে পারে তবে স্টাইল এবং পঠনযোগ্যতার দৃষ্টিভঙ্গির আরও একটি বিষয় রয়েছে।

প্রথমত - সরল পুরাতন ফর্ম লুপগুলি সরল এবং পুরানো। প্রত্যেকে তাদের ইতিমধ্যে জানে।

দ্বিতীয়ত এবং আরও গুরুত্বপূর্ণ - আপনি সম্ভবত Iterable.forEach ব্যবহার করতে চান শুধুমাত্র ওয়ান-লাইনার ল্যাম্বডাস দিয়ে। "দেহ" যদি ভারী হয়ে যায় - এগুলি পড়ার মতো নয়। এখান থেকে আপনার কাছে দুটি বিকল্প রয়েছে - অভ্যন্তরীণ ক্লাসগুলি (ইয়াক) ব্যবহার করুন বা সাধারণ প্লেইন ফর্ম লুপ ব্যবহার করুন। লোকেরা প্রায়শই বিরক্ত হয় যখন তারা একই জিনিসগুলি (সংগ্রহের উপরে পুনরাবৃত্তিগুলি) একই কোডবেজে বিভিন্ন উপায় / শৈলী সম্পন্ন করে দেখছে এবং এটি সম্ভবত এটি ঘটবে বলে মনে হচ্ছে।

আবার এটি হতে পারে বা নাও হতে পারে। কোডে কাজ করা লোকের উপর নির্ভর করে।


1
সমান্তরালত্বের জন্য নতুন "সমান্তরাল সংগ্রহ" দরকার নেই। এটি কেবল নির্ভর করে আপনি কোনও ধারাবাহিক স্ট্রিম (সংগ্রহ.স্ট্রিম () ব্যবহার করে) বা সমান্তরাল একের জন্য (সংগ্রহ.পেনালাল স্ট্রিম () ব্যবহার করে) চেয়েছিলেন কিনা তার উপর on
জেবি নিজেট

ডকুমেন্ট সংগ্রহ অনুসারে @ জেবিনিজেট.প্যারালাল স্ট্রিম () গ্যারান্টি দেয় না যে বাস্তবায়ন সংগ্রহ সমান্তরাল প্রবাহ ফিরে আসবে। আমি আসলে নিজেকে ভাবছি, কখন এটি ঘটতে পারে তবে সম্ভবত এটি সংগ্রহের উপর নির্ভর করে।
ইউজিন লয়

সম্মত হয়। এটি সংগ্রহের উপরও নির্ভর করে। তবে আমার বক্তব্যটি ছিল যে সমস্ত স্ট্যান্ডার্ড সংগ্রহ (অ্যারেলিস্ট ইত্যাদি) এর সাথে সমান্তরাল ফোর্যাচ লুপগুলি ইতিমধ্যে উপলব্ধ ছিল। "সমান্তরাল সংগ্রহ" অপেক্ষা করার দরকার নেই।
জেবি নিজত

@ জেবিনিজেট আপনার বক্তব্যটিতে একমত, তবে এটি "প্যারালাল কালেকশন" বলতে আমি প্রথম স্থানে ছিল না সেটাই সত্য নয়। আমি কালেকশন.প্যারালাল স্ট্রিম () উল্লেখ করি যা স্কেল এর ধারণার সাথে সাদৃশ্য দ্বারা জাভা 8-তে "সমান্তরাল সংগ্রহ" হিসাবে যুক্ত হয়েছিল যা বেশ কিছুটা একই কাজ করে। এছাড়াও, জেএসআর বিটে একে কীভাবে ডাকা হয় তা নিশ্চিত নই আমি এই জাভা 8 বৈশিষ্ট্যের জন্য একই রকম পরিভাষা ব্যবহার করে এমন বেশ কয়েকটি কাগজপত্র দেখেছি।
ইউজিন লয়

1
শেষ অনুচ্ছেদের জন্য আপনি কোনও ফাংশন রেফারেন্স ব্যবহার করতে পারেন:collection.forEach(MyClass::loopBody);
র‌্যাচেট ফ্রিক

6

সর্বাধিক উত্সাহজনক কার্যক্ষমতার forEachসীমাবদ্ধতাগুলির মধ্যে একটি হ'ল চেক করা ব্যতিক্রম সমর্থনগুলির অভাব।

একটি সম্ভাব্য কর্মসূচী হ'ল forEachপ্লেইন পুরানো ফোরচ লুপের সাথে টার্মিনাল প্রতিস্থাপন :

    Stream<String> stream = Stream.of("", "1", "2", "3").filter(s -> !s.isEmpty());
    Iterable<String> iterable = stream::iterator;
    for (String s : iterable) {
        fileWriter.append(s);
    }

ল্যাম্বডাস এবং স্ট্রিমগুলির মধ্যে চেক করা ব্যতিক্রম হ্যান্ডলিংয়ের সাথে অন্যান্য ওয়ার্কআরাউন্ডগুলির সাথে সর্বাধিক জনপ্রিয় প্রশ্নের তালিকা এখানে রয়েছে:

জাভা 8 লাম্বদা ফাংশন যে ব্যতিক্রম ছুঁড়ে?

জাভা 8: ল্যাম্বদা-স্ট্রিমস, ব্যতিক্রম সহ পদ্ধতি দ্বারা ফিল্টার

আমি জাভা 8 টি স্ট্রিমের মধ্যে থেকে চেক করা ব্যতিক্রমগুলি কীভাবে ফেলে দিতে পারি?

জাভা 8: ল্যাম্বডা এক্সপ্রেশনগুলিতে হ্যান্ডলিং বাধ্যতামূলকভাবে চেক করা ব্যতিক্রম। বাধ্যতামূলক কেন, notচ্ছিক নয়?


3

1.7 এরও বেশি প্রতিটি পদ্ধতির জাভা 1.8 এর সুবিধা লুপের জন্য বর্ধিত কোডটি লেখার সময় আপনি কেবল ব্যবসায়িক যুক্তিতে ফোকাস করতে পারেন।

forEach পদ্ধতিটি java.util.function.Conumer অবজেক্টটিকে একটি আর্গুমেন্ট হিসাবে গ্রহণ করে, সুতরাং এটি আমাদের ব্যবসায়িক যুক্তিটিকে একটি পৃথক স্থানে রাখতে সহায়তা করে যা আপনি যে কোনও সময় এটি পুনরায় ব্যবহার করতে পারেন।

নীচে স্নিপেট তাকান,

  • এখানে আমি একটি নতুন ক্লাস তৈরি করেছি যা গ্রাহক শ্রেণি থেকে ক্লাস পদ্ধতি গ্রহণের ওভাররাইড করবে, যেখানে আপনি অতিরিক্ত কার্যকারিতা যুক্ত করতে পারেন, আরও বেশি পরিমাণে আইট্রেশন .. !!!!!!

    class MyConsumer implements Consumer<Integer>{
    
        @Override
        public void accept(Integer o) {
            System.out.println("Here you can also add your business logic that will work with Iteration and you can reuse it."+o);
        }
    }
    
    public class ForEachConsumer {
    
        public static void main(String[] args) {
    
            // Creating simple ArrayList.
            ArrayList<Integer> aList = new ArrayList<>();
            for(int i=1;i<=10;i++) aList.add(i);
    
            //Calling forEach with customized Iterator.
            MyConsumer consumer = new MyConsumer();
            aList.forEach(consumer);
    
    
            // Using Lambda Expression for Consumer. (Functional Interface) 
            Consumer<Integer> lambda = (Integer o) ->{
                System.out.println("Using Lambda Expression to iterate and do something else(BI).. "+o);
            };
            aList.forEach(lambda);
    
            // Using Anonymous Inner Class.
            aList.forEach(new Consumer<Integer>(){
                @Override
                public void accept(Integer o) {
                    System.out.println("Calling with Anonymous Inner Class "+o);
                }
            });
        }
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.