জাভা "ডাবল ব্রেস সূচনা" এর দক্ষতা?


823

ইন জাভার লুকায়িত বৈশিষ্ট্য শীর্ষ উত্তর উল্লেখ ডাবল বন্ধনী সূচনা , একটি সঙ্গে খুব enticing শব্দবিন্যাস:

Set<String> flavors = new HashSet<String>() {{
    add("vanilla");
    add("strawberry");
    add("chocolate");
    add("butter pecan");
}};

এই আইডিয়োম এটিতে একটি উদাহরণ ইনিশিয়ালাইজার সহ একটি বেনামে অভ্যন্তরীণ শ্রেণি তৈরি করে, যা "সম্বলিত সুযোগে কোনও [...] পদ্ধতি ব্যবহার করতে পারে"।

মূল প্রশ্ন: এটি যেমন শোনাচ্ছে ততটা অক্ষম ? এর ব্যবহার কি এক-বন্ধের সূচনাতে সীমাবদ্ধ করা উচিত? (এবং অবশ্যই দেখানো হচ্ছে!)

দ্বিতীয় প্রশ্ন: নতুন হ্যাশসেটটি অবশ্যই "এই" ইনস্ট্যান্স ইনিশিয়ালাইজারে ব্যবহৃত হতে হবে ... কেউ কি প্রক্রিয়াটির বিষয়ে আলোকপাত করতে পারে?

তৃতীয় প্রশ্ন: এই আইডিয়মটি কি প্রোডাকশন কোডে ব্যবহার করা খুব অস্পষ্ট ?

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

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

প্রশ্ন (2) আমার কাছে সবচেয়ে আকর্ষণীয় বলে প্রমাণিত হয়েছিল। আমি যদি উত্তরগুলি বুঝতে পারি তবে ডিবিআইতে যা ঘটছে তা হ'ল বেনামে অভ্যন্তরীণ বর্গটি নতুন অপারেটর দ্বারা তৈরি করা অবজেক্টের শ্রেণিকে প্রসারিত করে এবং তাই উদাহরণটি তৈরির ক্ষেত্রে একটি "এই" মান রয়েছে। খুব ঝরঝরে.

সামগ্রিকভাবে, ডিবিআই আমাকে একটি বৌদ্ধিক কৌতূহল হিসাবে চিহ্নিত করে। কুলবার্ড এবং অন্যরা আপনাকে নির্দেশ করে যে আপনি অ্যারেএস.এললিস্ট, ভারার্গস পদ্ধতি, গুগল সংগ্রহ এবং প্রস্তাবিত জাভা 7 সংগ্রহের আক্ষরিক সাথে একই প্রভাব অর্জন করতে পারেন। স্কেলা, জেরুবি এবং গ্রোভির মতো আরও নতুন জেভিএম ভাষাও তালিকা তৈরির জন্য সংক্ষিপ্ত স্বরলিপিগুলি সরবরাহ করে এবং জাভা দিয়ে ভালভাবে আন্তঃসংযোগ স্থাপন করে। ডিবিআই ক্লাসপথকে গুঁড়িয়ে দিয়ে ক্লাস লোডকে কিছুটা কমিয়ে দেয় এবং কোডটিকে একটি বাছাই করে তোলে, আমি সম্ভবত এ থেকে দূরে থাকি। যাইহোক, আমি এই বন্ধুর কাছে এই বসন্তটি বয়ে আনার পরিকল্পনা করছি যিনি সবেমাত্র তার এসসিজেপি অর্জন করেছেন এবং জাভা শব্দার্থক সম্পর্কে ভাল প্রকৃতির জোস্টগুলি ভালবাসেন! ;-) ধন্যবাদ সবাইকে!

7/2017: বেলডাংয়ের ডাবল ব্রেস প্রারম্ভিককরণের একটি ভাল সংক্ষিপ্তসার রয়েছে এবং এটিকে একটি বিরোধী নিদর্শন হিসাবে বিবেচনা করে।

12/2017: @ বাসিল বাউর্ক নোট করেছেন যে নতুন জাভা 9-এ আপনি বলতে পারেন:

Set<String> flavors = Set.of("vanilla", "strawberry", "chocolate", "butter pecan");

এটা নিশ্চিতভাবে যেতে হবে। আপনি যদি পূর্ববর্তী সংস্করণটির সাথে আটকে থাকেন তবে গুগল সংগ্রহের ইমটুটেবলসেটটি একবার দেখুন


33
কোড গন্ধ আমি এখানে দেখতে যে সরল পাঠক আশা হল, flavorsএকটি হতে HashSet, কিন্তু হায় এটা একটি বেনামী উপশ্রেণী হয়।
এলাজার লাইবোভিচ

6
আপনি যদি পারফরম্যান্স লোড করার পরিবর্তে দৌড় বিবেচনা করেন তবে কোনও পার্থক্য নেই, আমার উত্তর দেখুন।
পিটার লরে

4
আমি ভালবাসি যে আপনি একটি সংক্ষিপ্তসার তৈরি করেছেন, আমি মনে করি আপনার উপলব্ধি এবং সম্প্রদায় উভয়ের পক্ষে এটি একটি উপযুক্ত অনুশীলন।
প্যাট্রিক মারফি

3
এটা আমার মতে অস্পষ্ট নয়। পাঠকদের জানা উচিত যে দ্বিগুণ ... ও অপেক্ষা করুন, @ ইলাজারলিবুভিচ ইতিমধ্যে তাঁর মন্তব্যে বলেছেন । ডাবল ব্রেস ইনিশিয়ালাইজার নিজেই একটি ভাষা নির্মাণ হিসাবে উপস্থিত নেই, এটি কেবল একটি বেনামে সাবক্লাস এবং একটি উদাহরণ সূচকটির সংমিশ্রণ। একমাত্র বিষয়, এটি সম্পর্কে মানুষের সচেতন হওয়া দরকার।
এমসি সম্রাট

8
জাভা 9 অপরিবর্তনীয় সেট স্ট্যাটিক ফ্যাক্টরি পদ্ধতিগুলি সরবরাহ করে যা কিছু পরিস্থিতিতে ডিসিআইয়ের ব্যবহার প্রতিস্থাপন করতে পারে:Set<String> flavors = Set.of( "vanilla" , "strawberry" , "chocolate" , "butter pecan" ) ;
বেসিল বার্ক

উত্তর:


607

বেনামে অভ্যন্তরীণ ক্লাসগুলি নিয়ে আমি যখন খুব দূরে থাকি তবে এখানে সমস্যাটি রয়েছে:

2009/05/27  16:35             1,602 DemoApp2$1.class
2009/05/27  16:35             1,976 DemoApp2$10.class
2009/05/27  16:35             1,919 DemoApp2$11.class
2009/05/27  16:35             2,404 DemoApp2$12.class
2009/05/27  16:35             1,197 DemoApp2$13.class

/* snip */

2009/05/27  16:35             1,953 DemoApp2$30.class
2009/05/27  16:35             1,910 DemoApp2$31.class
2009/05/27  16:35             2,007 DemoApp2$32.class
2009/05/27  16:35               926 DemoApp2$33$1$1.class
2009/05/27  16:35             4,104 DemoApp2$33$1.class
2009/05/27  16:35             2,849 DemoApp2$33.class
2009/05/27  16:35               926 DemoApp2$34$1$1.class
2009/05/27  16:35             4,234 DemoApp2$34$1.class
2009/05/27  16:35             2,849 DemoApp2$34.class

/* snip */

2009/05/27  16:35               614 DemoApp2$40.class
2009/05/27  16:35             2,344 DemoApp2$5.class
2009/05/27  16:35             1,551 DemoApp2$6.class
2009/05/27  16:35             1,604 DemoApp2$7.class
2009/05/27  16:35             1,809 DemoApp2$8.class
2009/05/27  16:35             2,022 DemoApp2$9.class

এই সমস্ত ক্লাস যা আমি একটি সাধারণ অ্যাপ্লিকেশন তৈরি করার সময় তৈরি হয়েছিল এবং প্রচুর পরিমাণে বেনামে অভ্যন্তরীণ ক্লাস ব্যবহার করেছি - প্রতিটি শ্রেণি একটি পৃথক classফাইলে সংকলিত হবে ।

"ডাবল ব্রেস ইনিশিয়ালাইজেশন", যেমনটি ইতিমধ্যে উল্লিখিত হয়েছে, এটি একটি বেনামি অভ্যন্তর শ্রেণীর সাথে একটি উদাহরণ ইনিশিয়ালাইজেশন ব্লক, যার অর্থ প্রতিটি "আরম্ভের" জন্য একটি নতুন বর্গ তৈরি করা হয়, সবগুলি সাধারণত একক বস্তু তৈরির উদ্দেশ্যে।

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

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


কেবলমাত্র রেফারেন্সের জন্য, ডাবল ব্রেস সূচনাটি নিম্নলিখিত:

List<String> list = new ArrayList<String>() {{
    add("Hello");
    add("World!");
}};

এটি জাভার কোনও "লুকানো" বৈশিষ্ট্যের মতো দেখায়, তবে এটি কেবল এটির একটি পুনর্লিখন:

List<String> list = new ArrayList<String>() {

    // Instance initialization block
    {
        add("Hello");
        add("World!");
    }
};

সুতরাং এটি মূলত একটি উদাহরণ শুরুর ব্লক যা একটি বেনামি অভ্যন্তর শ্রেণীর অংশ ।


প্রকল্প কয়েনের জন্য জোশুয়া ব্লচের সংগ্রহের লিটারালসের প্রস্তাবটি এই লাইনের সাথে ছিল:

List<Integer> intList = [1, 2, 3, 4];

Set<String> strSet = {"Apple", "Banana", "Cactus"};

Map<String, Integer> truthMap = { "answer" : 42 };

দুঃখিতভাবে, এটা তার পথ না তন্ন তন্ন জাভা 7 কিংবা 8 এবং অনির্দিষ্টকালের জন্য shelved হয়।


পরীক্ষা

এখানে সহজ পরীক্ষা আমি পরীক্ষিত করেছি - করতে 1000 ArrayListউপাদানের সঙ্গে গুলি "Hello"এবং "World!"এর মাধ্যমে তাদের যোগ করা addপদ্ধতি, দুটি পদ্ধতি ব্যবহার করছে:

পদ্ধতি 1: ডাবল ব্রেস সূচনা

List<String> l = new ArrayList<String>() {{
  add("Hello");
  add("World!");
}};

পদ্ধতি 2: ইনস্ট্যান্ট করুন একটি ArrayListএবংadd

List<String> l = new ArrayList<String>();
l.add("Hello");
l.add("World!");

আমি দুটি পদ্ধতি ব্যবহার করে 1000 টি সূচনা করার জন্য একটি জাভা উত্স ফাইলটি লিখতে একটি সাধারণ প্রোগ্রাম তৈরি করেছি:

পরীক্ষা 1:

class Test1 {
  public static void main(String[] s) {
    long st = System.currentTimeMillis();

    List<String> l0 = new ArrayList<String>() {{
      add("Hello");
      add("World!");
    }};

    List<String> l1 = new ArrayList<String>() {{
      add("Hello");
      add("World!");
    }};

    /* snip */

    List<String> l999 = new ArrayList<String>() {{
      add("Hello");
      add("World!");
    }};

    System.out.println(System.currentTimeMillis() - st);
  }
}

পরীক্ষা 2:

class Test2 {
  public static void main(String[] s) {
    long st = System.currentTimeMillis();

    List<String> l0 = new ArrayList<String>();
    l0.add("Hello");
    l0.add("World!");

    List<String> l1 = new ArrayList<String>();
    l1.add("Hello");
    l1.add("World!");

    /* snip */

    List<String> l999 = new ArrayList<String>();
    l999.add("Hello");
    l999.add("World!");

    System.out.println(System.currentTimeMillis() - st);
  }
}

দয়া করে মনে রাখবেন যে, 1000 ArrayListগুলি আর 1000 বেনামে অভ্যন্তরীণ বর্গগুলি প্রসারিত করার জন্য অতিবাহিত সময়টি ArrayListব্যবহার করে পরীক্ষা করা হয় System.currentTimeMillis, তাই টাইমারটির খুব বেশি রেজোলিউশন হয় না। আমার উইন্ডোজ সিস্টেমে রেজোলিউশনটি প্রায় 15-16 মিলিসেকেন্ড।

দুটি পরীক্ষার 10 রানের ফলাফল নিম্নলিখিত ছিল:

Test1 Times (ms)           Test2 Times (ms)
----------------           ----------------
           187                          0
           203                          0
           203                          0
           188                          0
           188                          0
           187                          0
           203                          0
           188                          0
           188                          0
           203                          0

যেমন দেখা যায়, ডাবল ব্রেস প্রারম্ভিকালে প্রায় 190 এমএসের লক্ষণীয় কার্যকর কার্যকর সময় থাকে has

ইতিমধ্যে, ArrayListআরম্ভের কার্যকরকরণের সময়টি 0 এমএস থেকে বেরিয়ে এসেছিল। অবশ্যই, টাইমার রেজোলিউশনটি বিবেচনায় নেওয়া উচিত, তবে এটি 15 এমএসের নিচে হওয়ার সম্ভাবনা রয়েছে।

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

এবং হ্যাঁ, ডাবল ব্রেস প্রারম্ভিককরণ পরীক্ষা প্রোগ্রাম .classসংকলন করে 1000 টি ফাইল তৈরি হয়েছিল Test1


10
"সম্ভবত" অপারেটিভ শব্দ হচ্ছে। পরিমাপ না করা, কর্মক্ষমতা সম্পর্কে কোন বিবৃতি অর্থবহ হয়।
ইনস্ট্যান্স হান্টার

16
আপনি এত বড় কাজ করেছেন আমি খুব কমই এটি বলতে চাই, তবে টেস্ট ১ বার ক্লাসের বোঝা দ্বারা প্রভাবিত হতে পারে। লুপের জন্য প্রত্যেকটি পরীক্ষার একক দৃষ্টান্তটি 1000 বার চালানো দেখতে পারা আকর্ষণীয় হবে, তারপরে এটি এক সেকেন্ডে আবার 1000 বা 10,000 বারের লুপের জন্য চালনা করুন এবং সময়ের পার্থক্য (System.nanoTime ()) মুদ্রণ করুন। লুপের জন্য প্রথমটি সমস্ত উষ্ণতর প্রভাবগুলি (জেআইটি, শ্রেণীবদ্ধ, যেমন) কেটে যায়। উভয় পরীক্ষা যদিও বিভিন্ন ক্ষেত্রে ব্যবহারের মডেল। আমি আগামীকাল কাজের সময় এটি চালানোর চেষ্টা করব।
জিম ফেরানস

8
@ জিম ফেরানস: আমি মোটামুটি নিশ্চিত যে টেস্ট ১ বার ক্লাসের বোঝা থেকে আসে। তবে, ডাবল ব্রেস প্রারম্ভিককরণ ব্যবহারের ফলাফলটি শ্রেণি বোঝা থেকে সামলাতে হচ্ছে। আমি বিশ্বাস করি ডাবল ব্রেস ডিআইডি জন্য বেশিরভাগ ক্ষেত্রে ব্যবহার হয়। এককালীন সূচনার জন্য, পরীক্ষাটি এই ধরণের সূচনাটির সাধারণ ব্যবহারের ক্ষেত্রে আরও নিকটবর্তী। আমি বিশ্বাস করব যে প্রতিটি পরীক্ষার একাধিক পুনরাবৃত্তি সম্পাদন সময় ব্যবধানকে আরও ছোট করে তোলে।
কুলবার্ড

73
এটি যা প্রমাণ করে তা হ'ল) ​​ক) ডাবল-ব্রেস সূচনাটি ধীর গতিতে এবং খ) আপনি যদি এটি 1000 বার করেন তবে আপনি সম্ভবত এই পার্থক্যটি লক্ষ্য করবেন না। এবং এটি এর মতো নয় যে হয় কোনও অভ্যন্তরীণ লুপের ক্ষেত্রেও বাধা হতে পারে। এটি খুব খারাপ সময়ে একটি ক্ষুদ্র ওয়ান-টাইম জরিমানা চাপায়।
মাইকেল মায়ার্স

15
যদি ডিবিআই ব্যবহার করে কোডটি আরও পাঠযোগ্য বা ভাবপ্রবণ হয় তবে এটি ব্যবহার করুন। জেভিএমের যে কাজটি এটি সামান্য বাড়ায় তা কোনও বৈধ যুক্তি নয়, এটি নিজেই এর বিরুদ্ধে। যদি এটি হয় তবে আমাদের অতিরিক্ত সহায়ক পদ্ধতি / ক্লাস সম্পর্কেও উদ্বিগ্ন হওয়া উচিত, পরিবর্তে কম পদ্ধতিতে বিশাল ক্লাসগুলি পছন্দ করা ...
রোজরিও

105

এই পদ্ধতির একটি সম্পত্তি যা এখনও অবধি নির্দেশ করা যায়নি তা হ'ল আপনি অভ্যন্তরীণ ক্লাস তৈরি করার কারণে পুরো ধারণক্ষম শ্রেণিটি তার পরিধিতে ধরা পড়ে। এর অর্থ হ'ল যতক্ষণ আপনার সেট জীবিত থাকবে ততক্ষণ এটি অন্তর্ভুক্ত দৃষ্টান্তের জন্য একটি পয়েন্টার ধরে রাখবে (this$0 ) যুক্ত আবর্জনা সংগ্রহ করা থেকে বিরত একটি সমস্যা হতে পারে।

এটি এবং সত্য যে একটি নিয়মিত হ্যাশসেট ঠিক সূক্ষ্ম (বা আরও ভাল) কাজ করবে যদিও একটি নতুন শ্রেণি প্রথম স্থানে তৈরি হয়েছিল, আমাকে এই নির্মাণটি ব্যবহার করতে চায় না (যদিও আমি সিনট্যাকটিক চিনির জন্য সত্যই আগ্রহী)।

দ্বিতীয় প্রশ্ন: নতুন হ্যাশসেটটি অবশ্যই "এই" ইনস্ট্যান্স ইনিশিয়ালাইজারে ব্যবহৃত হতে হবে ... কেউ কি প্রক্রিয়াটির বিষয়ে আলোকপাত করতে পারে? আমি "সাদামাটা" প্রত্যাশা করতাম "এটি" অবজেক্টটি "স্বাদগুলি" আরম্ভ করার জন্য উল্লেখ করুন।

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

public class Test {

    public void add(Object o) {
    }

    public Set<String> makeSet() {
        return new HashSet<String>() {
            {
              add("hello"); // HashSet
              Test.this.add("hello"); // outer instance 
            }
        };
    }
}

বেনামে সাবক্লাস তৈরি হচ্ছে তা পরিষ্কার করার জন্য আপনি সেখানে পদ্ধতিগুলিও সংজ্ঞায়িত করতে পারেন। উদাহরণস্বরূপ ওভাররাইডHashSet.add()

    public Set<String> makeSet() {
        return new HashSet<String>() {
            {
              add("hello"); // not HashSet anymore ...
            }

            @Override
            boolean add(String s){

            }

        };
    }

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

ডেটাস্ট্রাক্টের সিরিয়ালাইজেশন জড়িত থাকলে ধারণক্ষম শ্রেণীর উল্লেখটি বিপজ্জনক হতে পারে। ধারণক্ষম শ্রেণিটিও সিরিয়ালীকৃত হবে এবং সুতরাং অবশ্যই সিরিয়ালাইজেবল হতে হবে। এটি অস্পষ্ট ত্রুটি হতে পারে।
মাত্র

56

প্রতিবার কেউ ডাবল ব্রেস সূচনা ব্যবহার করলে, একটি বিড়ালছানা মারা যায়।

সিনট্যাক্সটি বরং অস্বাভাবিক এবং সত্যই মূmatic় নয় (স্বাদ বিতর্কযোগ্য, অবশ্যই) বাদে আপনি নিজের প্রয়োগে অপ্রয়োজনীয়ভাবে দুটি তাত্পর্যপূর্ণ সমস্যা তৈরি করছেন, যা আমি সম্প্রতি এখানে আরও বিস্তারিতভাবে ব্লগ করেছি here

1. আপনি অনেকগুলি বেনামী ক্লাস তৈরি করছেন

প্রতিবার আপনি ডাবল ব্রেস সূচনাটি ব্যবহার করে একটি নতুন ক্লাস তৈরি করা হয়। যেমন এই উদাহরণ:

Map source = new HashMap(){{
    put("firstName", "John");
    put("lastName", "Smith");
    put("organizations", new HashMap(){{
        put("0", new HashMap(){{
            put("id", "1234");
        }});
        put("abc", new HashMap(){{
            put("id", "5678");
        }});
    }});
}};

... এই ক্লাস উত্পাদন করবে:

Test$1$1$1.class
Test$1$1$2.class
Test$1$1.class
Test$1.class
Test.class

এটি আপনার ক্লাসলোডারের পক্ষে বেশ কিছুটা ওভারহেড - কিছুই নয়! অবশ্যই একবার ব্যবহার করলে অবশ্যই এটি আরম্ভের সময় খুব বেশি সময় নেয় না। তবে আপনি যদি আপনার এন্টারপ্রাইজ অ্যাপ্লিকেশন জুড়ে এই 20'000 বার করেন ... কেবলমাত্র "সিনট্যাক্স চিনির" জন্য এই সমস্ত গাদা স্মৃতি?

২. আপনি সম্ভবত একটি মেমরি ফাঁস তৈরি করছেন!

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

public class ReallyHeavyObject {

    // Just to illustrate...
    private int[] tonsOfValues;
    private Resource[] tonsOfResources;

    // This method almost does nothing
    public Map quickHarmlessMethod() {
        Map source = new HashMap(){{
            put("firstName", "John");
            put("lastName", "Smith");
            put("organizations", new HashMap(){{
                put("0", new HashMap(){{
                    put("id", "1234");
                }});
                put("abc", new HashMap(){{
                    put("id", "5678");
                }});
            }});
        }};

        return source;
    }
}

প্রত্যাবর্তিতগুলিতে Mapএখন সংলগ্ন দৃষ্টান্তের একটি উল্লেখ থাকবে ReallyHeavyObject। আপনি সম্ভবত এটি ঝুঁকি নিতে চান না:

মেমরি ফুটো এখানে

Http://blog.jooq.org/2014/12/08/dont-be-clever-the-double-curly-braces-anti-pattern/ থেকে চিত্র

৩. আপনি ভান করতে পারেন যে জাভাতে মানচিত্রের অক্ষর রয়েছে

আপনার আসল প্রশ্নের উত্তর দেওয়ার জন্য, লোকেরা এই সিনট্যাক্সটি ব্যবহার করে ব্যবহার করছে যে জাভাতে মানচিত্রের আক্ষরিক মতো কিছু রয়েছে, বিদ্যমান অ্যারে লিটারেলের মতো:

String[] array = { "John", "Doe" };
Map map = new HashMap() {{ put("John", "Doe"); }};

কিছু লোকেরা এটিকে সিন্ট্যাক্টিক্যালি উদ্দীপক বলে মনে করতে পারেন।


7
বিড়ালছানা সংরক্ষণ করুন! ভাল উত্তর!
এরিস 2 ওয়ার্ল্ড

36

নিম্নলিখিত পরীক্ষার ক্লাস নেওয়া:

public class Test {
  public void test() {
    Set<String> flavors = new HashSet<String>() {{
        add("vanilla");
        add("strawberry");
        add("chocolate");
        add("butter pecan");
    }};
  }
}

এবং তারপরে ক্লাস ফাইলটি ডিকম্পিলিং করে আমি দেখছি:

public class Test {
  public void test() {
    java.util.Set flavors = new HashSet() {

      final Test this$0;

      {
        this$0 = Test.this;
        super();
        add("vanilla");
        add("strawberry");
        add("chocolate");
        add("butter pecan");
      }
    };
  }
}

এটি আমার পক্ষে মারাত্মকভাবে অদক্ষ বলে মনে হচ্ছে না। আমি যদি এই জাতীয় কোনও কিছুর জন্য পারফরম্যান্স নিয়ে চিন্তিত হয়ে থাকি তবে আমি এটির প্রোফাইল করব। এবং আপনার প্রশ্নের # 2 উপরের কোড দ্বারা উত্তর দেওয়া হয়েছে: আপনি আপনার অভ্যন্তর শ্রেণীর জন্য একটি নিখুঁত নির্মাণকারী (এবং উদাহরণস্বরূপ প্রাথমিক) এর ভিতরে আছেন, সুতরাং thisএই অভ্যন্তরীণ শ্রেণিকে " " বোঝায়।

হ্যাঁ, এই বাক্য গঠনটি অস্পষ্ট, তবে একটি মন্তব্য অস্পষ্ট সিনট্যাক্সের ব্যবহারকে স্পষ্ট করতে পারে। বাক্য গঠনটি পরিষ্কার করতে, বেশিরভাগ লোক স্ট্যাটিক ইনিশিয়ালাইজার ব্লকের সাথে পরিচিত (জেএলএস 8.7 স্ট্যাটিক ইনিশিয়ালাইজারস):

public class Sample1 {
    private static final String someVar;
    static {
        String temp = null;
        ..... // block of code setting temp
        someVar = temp;
    }
}

আপনি staticকনস্ট্রাক্টর ব্যবহারের জন্য অনুরূপ একটি সিনট্যাক্স (" " শব্দটি ছাড়াই ) ব্যবহার করতে পারেন (জেএলএস 8.6 ইনস্ট্যান্স ইনিশিয়ালাইজার), যদিও আমি প্রযোজনা কোডে এটি কখনও দেখিনি। এটি সাধারণভাবে কম পরিচিত।

public class Sample2 {
    private final String someVar;

    // This is an instance initializer
    {
        String temp = null;
        ..... // block of code setting temp
        someVar = temp;
    }
}

আপনার কোনো ডিফল্ট কন্সট্রাকটর, তারপর মধ্যে কোডের ব্লক না থাকে তাহলে {}কম্পাইলার দ্বারা কন্সট্রাকটর পরিণত হয়। এটিকে মাথায় রেখে, ডাবল ব্রেস কোডটি খুলে ফেলুন:

public void test() {
  Set<String> flavors = new HashSet<String>() {
      {
        add("vanilla");
        add("strawberry");
        add("chocolate");
        add("butter pecan");
      }
  };
}

অভ্যন্তরীণ-সর্বাধিক ধনুর্বন্ধনীগুলির মধ্যে কোডের ব্লকটি কম্পাইলার দ্বারা নির্মাত্রে রূপান্তরিত হয়। বহিরাগত সর্বাধিক ধনুর্বন্ধনী বেনামে অনাময় অভ্যন্তর শ্রেণি সীমাবদ্ধ করে। সবকিছুকে অজ্ঞাতনামা করার চূড়ান্ত পদক্ষেপ নিতে:

public void test() {
  Set<String> flavors = new MyHashSet();
}

class MyHashSet extends HashSet<String>() {
    public MyHashSet() {
        add("vanilla");
        add("strawberry");
        add("chocolate");
        add("butter pecan");
    }
}

প্রারম্ভিককরণের উদ্দেশ্যে, আমি বলব যা কিছু নেই (বা এত ছোট যে এটি উপেক্ষিত হতে পারে)। যাইহোক, প্রতিটি ব্যবহার flavorsবিপরীতে HashSetনয় বরং এর বিরুদ্ধে হবেMyHashSet । এটির উপরে সম্ভবত একটি ছোট (এবং সম্ভবত যথেষ্ট তুচ্ছ) head তবে আবার, আমি এটি সম্পর্কে উদ্বিগ্ন হওয়ার আগে, আমি এটি প্রোফাইল করব।

আবার আপনার প্রশ্ন # 2 তে, উপরের কোডটি ডাবল ব্রেস প্রারম্ভিকরণের যৌক্তিক এবং সুস্পষ্ট সমতুল্য এবং এটি এটি স্পষ্ট করে তোলে যেখানে " this" বোঝায়: প্রসারিত অভ্যন্তর শ্রেণীর কাছেHashSet

উদাহরণস্বরূপ প্রাথমিকের বিবরণ সম্পর্কে আপনার যদি প্রশ্ন থাকে তবে জেএলএস ডকুমেন্টেশনে বিশদটি দেখুন ।


এডি, খুব সুন্দর ব্যাখ্যা। যদি জেভিএম বাইট কোডগুলি ডিসেমপ্লেশন হিসাবে পরিষ্কার থাকে তবে মৃত্যুদন্ড কার্যকর করার গতিটি যথেষ্ট দ্রুত হবে, যদিও আমি অতিরিক্ত .class ফাইলের বিশৃঙ্খলা সম্পর্কে কিছুটা উদ্বিগ্ন। আমি এখনও আগ্রহী যে ইন্সট্যান্ট ইনিশিয়ালাইজারটির নির্মাতা কেন "এটি" কে নতুন হ্যাশসেট <স্ট্রিং> উদাহরণ হিসাবে দেখেন এবং পরীক্ষার উদাহরণ নয়। আইডিয়ামটি সমর্থন করার জন্য এটি কি সর্বশেষ জাভা ল্যাঙ্গুয়েজ স্পেসিফিকেশনে স্পষ্টভাবে বর্ণিত আচরণ?
জিম ফেরানস

আমি আমার উত্তর আপডেট। আমি টেস্ট ক্লাসের বয়লারপ্লেটটি ছেড়ে দিয়েছিলাম, যা বিভ্রান্তির কারণ হয়েছিল। বিষয়গুলিকে আরও সুস্পষ্ট করার জন্য আমি এটি আমার উত্তরে রেখেছি। আমি এই আইডিয়ামটিতে ব্যবহৃত ইন্সট্যান্স ইনিশিয়াল ব্লকগুলির জন্য জেএলএস বিভাগটিও উল্লেখ করি।
এডি

1
@ জিম "এটি" এর ব্যাখ্যা বিশেষ ঘটনা নয়; এটি কেবলমাত্র অন্তর্নিহিত সংযুক্তকারী শ্রেণীর উদাহরণকে বোঝায়, যা হ্যাশসেট <স্ট্রিং> এর বেনামে সাবক্লাস।
নাথান কিচেন

সাড়ে চার বছর পরে লাফ দেওয়ার জন্য দুঃখিত। তবে পচা ক্লাস ফাইল (আপনার দ্বিতীয় কোড ব্লক) সম্পর্কে দুর্দান্ত জিনিসটি এটি বৈধ জাভা নয়! এটি super()অন্তর্নিহিত কন্সট্রাক্টরের দ্বিতীয় লাইন হিসাবে রয়েছে তবে এটি আগে আসতে হবে। (আমি এটি পরীক্ষা করেছি এবং এটি সংকলন করবে না))
চিয়েস্টিক-সুরক্ষা

1
@ চিয়েস্টিক-সুরক্ষা: কখনও কখনও ডিকম্পিলারগুলি কোড তৈরি করে যা সংকলন করে না।
এডি

35

ফুটো প্রবণ

আমি চিম ইন করার সিদ্ধান্ত নিয়েছি performance পারফরম্যান্স প্রভাবের মধ্যে রয়েছে: ডিস্ক অপারেশন + আনজিপ (জারের জন্য), শ্রেণি যাচাইকরণ, পের-জেন স্পেস (সান এর হটস্পট জেভিএম এর জন্য)। তবে সবচেয়ে খারাপ: এটি ফুটো প্রবণ। আপনি কেবল ফিরে আসতে পারবেন না।

Set<String> getFlavors(){
  return Collections.unmodifiableSet(flavors)
}

সুতরাং যদি সেটটি কোনও অন্য শ্রেণি লোডার দ্বারা লোড করা অন্য কোনও অংশে পালিয়ে যায় এবং সেখানে একটি রেফারেন্স রাখা হয়, তবে ক্লাস + শ্রেণি লোডারের পুরো গাছটি ফাঁস হয়ে যায়। এটি এড়াতে, হ্যাশম্যাপে একটি অনুলিপি প্রয়োজনীয় new LinkedHashSet(new ArrayList(){{add("xxx);add("yyy");}}),। আর কিউট না। আমি নিজের প্রতিমাটি ব্যবহার করি না, পরিবর্তে এটি পছন্দ হয় new LinkedHashSet(Arrays.asList("xxx","YYY"));


3
ভাগ্যক্রমে, জাভা 8 হিসাবে, PermGen আর জিনিস নয়। আমার মনে হয় এখনও প্রভাব আছে, তবে খুব সম্ভবত অস্পষ্ট ত্রুটির বার্তাটি নেই।
জোয়

2
@ জো, মেমরিটি সরাসরি জিসি (পারম জেনার) দ্বারা পরিচালিত হয় বা না করে শূন্য পার্থক্য করে। মেটাস্পেসে ফাঁস হওয়া এখনও একটি ফাঁস, যদি মেটা সীমাবদ্ধ না থাকে তবে লিনাক্সের ওম_কিলারের মতো স্টাফ দিয়ে কোনও ওওএম (পারম জেনার বাইরে) থাকবে না
বেটসেস

19

অনেকগুলি ক্লাস লোড করা শুরুতে কিছু মিলিসেকেন্ড যুক্ত করতে পারে। স্টার্টআপটি যদি এতটা সমালোচনা না করে থাকে এবং আপনি স্টার্টআপের পরে ক্লাসগুলির দক্ষতার দিকে তাকান তবে কোনও পার্থক্য নেই।

package vanilla.java.perfeg.doublebracket;

import java.util.*;

/**
 * @author plawrey
 */
public class DoubleBracketMain {
    public static void main(String... args) {
        final List<String> list1 = new ArrayList<String>() {
            {
                add("Hello");
                add("World");
                add("!!!");
            }
        };
        List<String> list2 = new ArrayList<String>(list1);
        Set<String> set1 = new LinkedHashSet<String>() {
            {
                addAll(list1);
            }
        };
        Set<String> set2 = new LinkedHashSet<String>();
        set2.addAll(list1);
        Map<Integer, String> map1 = new LinkedHashMap<Integer, String>() {
            {
                put(1, "one");
                put(2, "two");
                put(3, "three");
            }
        };
        Map<Integer, String> map2 = new LinkedHashMap<Integer, String>();
        map2.putAll(map1);

        for (int i = 0; i < 10; i++) {
            long dbTimes = timeComparison(list1, list1)
                    + timeComparison(set1, set1)
                    + timeComparison(map1.keySet(), map1.keySet())
                    + timeComparison(map1.values(), map1.values());
            long times = timeComparison(list2, list2)
                    + timeComparison(set2, set2)
                    + timeComparison(map2.keySet(), map2.keySet())
                    + timeComparison(map2.values(), map2.values());
            if (i > 0)
                System.out.printf("double braced collections took %,d ns and plain collections took %,d ns%n", dbTimes, times);
        }
    }

    public static long timeComparison(Collection a, Collection b) {
        long start = System.nanoTime();
        int runs = 10000000;
        for (int i = 0; i < runs; i++)
            compareCollections(a, b);
        long rate = (System.nanoTime() - start) / runs;
        return rate;
    }

    public static void compareCollections(Collection a, Collection b) {
        if (!a.equals(b) && a.hashCode() != b.hashCode() && !a.toString().equals(b.toString()))
            throw new AssertionError();
    }
}

কপি করে প্রিন্ট

double braced collections took 36 ns and plain collections took 36 ns
double braced collections took 34 ns and plain collections took 36 ns
double braced collections took 36 ns and plain collections took 36 ns
double braced collections took 36 ns and plain collections took 36 ns
double braced collections took 36 ns and plain collections took 36 ns
double braced collections took 36 ns and plain collections took 36 ns
double braced collections took 36 ns and plain collections took 36 ns
double braced collections took 36 ns and plain collections took 36 ns
double braced collections took 36 ns and plain collections took 36 ns

2
ডিবিআই অতিরিক্ত ব্যবহার করা না হলে আপনার পারমজেন স্পেসটি বাষ্পীভূত হবে No কমপক্ষে, আপনি যদি ক্লাস-আনলোডিং এবং পার্মজেন স্থানের আবর্জনা-সংগ্রহের অনুমতি দেওয়ার জন্য কিছু অস্পষ্ট জেভিএম বিকল্পগুলি সেট না করেন তবে তা হবে । সার্ভার-পার্শ্বের ভাষা হিসাবে জাভাটির প্রসার দেওয়া, মেমরি / পার্মজেন অন্তত একটি উল্লেখের পরোয়ানা জারি করে।
আরথ

1
@ আরথ এটি একটি ভাল বিষয় is আমি স্বীকার করি যে জাভাতে কাজ করার 16 বছরের মধ্যে আমি কখনই এমন কোনও সিস্টেমে কাজ করিনি যেখানে কোডের আকারে আমি যে সিস্টেমগুলি কাজ করেছি সেগুলির জন্য আপনাকে সর্বদা যুক্তিযুক্তভাবে ছোট রাখা হয়েছিল।
পিটার লরে

2
এর চেয়ে শর্তগুলি কী compareCollectionsএকত্রিত হওয়া ||উচিত নয় &&? ব্যবহারটি &&কেবল শব্দার্থগতভাবেই ভুল বলে মনে হচ্ছে না, এটি কার্যকারিতাটি পরিমাপের অভিপ্রায়কে প্রতিহত করে, কারণ কেবল প্রথম শর্তটিই একেবারে পরীক্ষা করা হবে। এছাড়াও, একটি স্মার্ট অপ্টিমাইজার সনাক্ত করতে পারে যে পুনরাবৃত্তির সময় শর্তগুলি কখনই বদলাবে না।
হলগার

@ আরথ ঠিক একটি আপডেট হিসাবে: জাভা 8 যেহেতু ভিএম আর কোনও পারম-জেন ব্যবহার করে না।
অ্যাঞ্জেল ও'স্পিয়ার 13

16

সেট তৈরি করতে আপনি ডাবল-ব্রেস প্রারম্ভিককরণের পরিবর্তে একটি ভারার্গস কারখানা পদ্ধতি ব্যবহার করতে পারেন:

public static Set<T> setOf(T ... elements) {
    return new HashSet<T>(Arrays.asList(elements));
}

গুগল কালেকশন লাইব্রেরিতে এর মতো সুবিধামত পদ্ধতি রয়েছে, পাশাপাশি অন্যান্য দরকারী কার্যকারিতাও রয়েছে।

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


Hah! ;-) আমি আসলে 1.2 দিন থেকে জাভা ফিরে একটি প্রচুর ঘুমোয় আছি (আমি এ VoiceXML ভয়েস ওয়েব ব্রাউজার লিখেছিলেন evolution.voxeo.com জাভা)। জেনারিকস, প্যারামিটারাইজড প্রকারগুলি, সংগ্রহগুলি, জাভা.ইটি.এল.কন্ট্রন্ট, লুপ সিনট্যাক্সের জন্য নতুন ইত্যাদি শিখতে মজাদার হয়েছে এখন এটি আরও ভাল ভাষা। আপনার বক্তব্য, ডিবিআইয়ের পেছনের প্রক্রিয়াটি প্রথমে অস্পষ্ট মনে হলেও, কোডটির অর্থ বেশ পরিষ্কার হওয়া উচিত।
জিম ফেরানস

10

দক্ষতা একদিকে রেখে, আমি খুব কমই নিজেকে ইউনিট পরীক্ষার বাইরে ঘোষণামূলক সংগ্রহ তৈরির জন্য আগ্রহী দেখতে পাই। আমি বিশ্বাস করি যে ডাবল ব্রেস বাক্য গঠনটি খুব পঠনযোগ্য।

বিশেষত তালিকার ঘোষণামূলক নির্মাণ অর্জনের আরেকটি উপায় হ'ল এর Arrays.asList(T ...)মতো ব্যবহার করা :

List<String> aList = Arrays.asList("vanilla", "strawberry", "chocolate");

এই পদ্ধতির সীমাবদ্ধতা অবশ্যই যে আপনি নির্দিষ্ট ধরণের তালিকা তৈরি করতে পারবেন না।


1
অ্যারে.এএসলিস্ট () হ'ল আমি সাধারণত ব্যবহার করতাম তবে আপনি ঠিক বলেছেন, এই পরিস্থিতিটি মূলত ইউনিট পরীক্ষায় উত্থিত হয়; রিয়েল কোডগুলি ডিবি কোয়েরি, এক্সএমএল এবং আরও কিছু থেকে তালিকা তৈরি করবে।
জিম ফেরানস

7
যদিও অ্যাসলিস্ট থেকে সাবধান থাকুন: প্রত্যাবর্তিত তালিকার উপাদানগুলি যোগ করা বা অপসারণ সমর্থন করে না। যখনই আমি অ্যাসলিস্টটি ব্যবহার করি, ফলস্বরূপ তালিকাটি new ArrayList<String>(Arrays.asList("vanilla", "strawberry", "chocolate"))এই সমস্যাটি ঘটাতে পছন্দ করে এমন একটি নির্মাণকারীর মধ্যে দিয়ে যাই ।
মাইকেল ময়র্স

7

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

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

(2) এ, আপনি কোনও অবজেক্টের কনস্ট্রাক্টরের অভ্যন্তরে, সুতরাং "এটি" আপনি যে অবজেক্টটি নির্মাণ করছেন তা বোঝায়। এটি অন্য কোনও নির্মাণকারীর থেকে আলাদা নয়।

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


5

ডাবল-ব্রেস সূচনা একটি অপ্রয়োজনীয় হ্যাক যা মেমরি ফাঁস এবং অন্যান্য সমস্যাগুলির পরিচয় দিতে পারে

এই "কৌশল" ব্যবহার করার কোনও বৈধ কারণ নেই। পেয়ারা দুর্দান্ত অপরিবর্তনীয় সংগ্রহ সরবরাহ করে যার মধ্যে স্ট্যাটিক কারখানা এবং নির্মাতারা উভয়ই অন্তর্ভুক্ত থাকে, যেখানে আপনি আপনার সংগ্রহকে এটি পরিষ্কার, পাঠযোগ্য এবং নিরাপদে ঘোষণা করেছেন declared বাক্য বিন্যাসে

প্রশ্নের উদাহরণটি হয়ে যায়:

Set<String> flavors = ImmutableSet.of(
    "vanilla", "strawberry", "chocolate", "butter pecan");

এটি কেবল এই খাটো এবং সহজেই পড়া সহজ নয়, তবে এটি অন্যান্য উত্তরে বর্ণিত ডাবল-ব্রেসড প্যাটার্ন সহ অসংখ্য সমস্যা এড়ায় । অবশ্যই, এটি সরাসরি নির্মিত-অনুরূপভাবে সম্পাদন করেHashMap তবে এটি বিপজ্জনক এবং ত্রুটি-প্রবণ এবং আরও ভাল বিকল্প রয়েছে।

যে কোনও সময় আপনি নিজেকে ডাবল-ব্রেসড সূচনা হিসাবে বিবেচনা করে দেখলে আপনার API গুলি পুনরায় পরীক্ষা করা উচিত বা নতুন পরিচিতি দেওয়া উচিত সিনট্যাকটিক ট্রিক্সের সুযোগ না দিয়ে সমস্যার যথাযথভাবে সমাধানের জন্য ।

ত্রুটি-প্রবণ এখন এই অ্যান্টি-প্যাটার্নটিকে ফ্ল্যাগ করে


-1। কিছু বৈধ পয়েন্ট থাকা সত্ত্বেও, এই উত্তরটি "কীভাবে অপ্রয়োজনীয় বেনাম শ্রেণি তৈরি করা এড়ানো যায়? আরও বেশি ক্লাস সহ একটি কাঠামো ব্যবহার করুন!"
এজেন্ট_এল

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

এবং ঠিক কীভাবে ডাবল ব্রেস সূচনাটি মরিরি ফুটো হতে পারে?
এঞ্জেল ও'স্পিয়ার 13

@ অ্যাঞ্জেলো'স্ফিয়ার ডিবিআই একটি অভ্যন্তরীণ শ্রেণি তৈরির একটি অপ্রচলিত উপায় , এবং তাই এর ঘেরযুক্ত শ্রেণির একটি অন্তর্নিহিত রেফারেন্স ধরে রাখে (যদি না শুধুমাত্র প্রাসঙ্গিক staticক্ষেত্রে ব্যবহৃত হয় )। আমার প্রশ্নের নীচে ত্রুটি-প্রবণ লিঙ্কটি এটি আরও আলোচনা করে।
dimo414

আমি বলব এটি স্বাদের বিষয়। এবং সত্যই এটি সম্পর্কে বিস্মৃত হয়।
অ্যাঞ্জেল ও'স্পিয়ার

4

আমি এটি নিয়ে গবেষণা করছিলাম এবং বৈধ উত্তরের দ্বারা সরবরাহিত পরীক্ষার চেয়ে গভীরতর পরীক্ষা করার সিদ্ধান্ত নিয়েছি।

এখানে কোডটি রয়েছে: https://gist.github.com/4368924

এবং এটি আমার উপসংহার

আমি অবাক হয়ে জানতে পেরেছিলাম যে বেশিরভাগ রান পরীক্ষায় অভ্যন্তরীণ দীক্ষা আসলে দ্রুত ছিল (কিছু ক্ষেত্রে প্রায় দ্বিগুণ)। বিপুল সংখ্যক নিয়ে কাজ করার সময় সুবিধাটি হু হু করে ফেলা হবে বলে মনে হয়।

মজার বিষয় হচ্ছে লুপটিতে 3 টি বস্তু তৈরি করে এমন কেসটি হ'ল এটি অন্যান্য সুবিধার চেয়ে খুব শীঘ্রই উপকার হারায়। আমি নিশ্চিত না কেন এটি হচ্ছে এবং কোনও সিদ্ধান্তে পৌঁছানোর জন্য আরও পরীক্ষা করা উচিত। কংক্রিট বাস্তবায়ন তৈরি করা ক্লাস সংজ্ঞাটি পুনরায় লোড করা এড়াতে সহায়তা করতে পারে (যদি তা হ'ল)

তবে এটি স্পষ্ট যে একক আইটেম বিল্ডিংয়ের জন্য এটি বেশিরভাগ ক্ষেত্রে এমনকি প্রচুর সংখ্যক পরিমাণেও লক্ষ্য করা যায় না over

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

আমার উপসংহার? যতক্ষণ এটি অপব্যবহার না করা হয় ততক্ষণ তা ব্যবহার করা ঠিক হবে।

আমার সম্পর্কে আপনি কী মনে করেন জানি :)


2
এটি কোনও বৈধ পরীক্ষা নয়। কোডটি তাদের ব্যবহার না করেই অবজেক্ট তৈরি করে যা অপ্টিমাইজারটিকে পুরো উদাহরণটি তৈরি করতে সহায়তা করে। কেবলমাত্র অবশিষ্ট পার্শ্ব-প্রতিক্রিয়া হ'ল এলোমেলো নম্বর ক্রমের অগ্রযাত্রা যার ওভারহেড এই পরীক্ষাগুলিতে অন্য যে কোনও কিছুকে ছাড়িয়ে যায়।
হলগার

3

আমি নেটের জবাব দ্বিতীয়, আমি ব্যতীত তালিকা তৈরি এবং তাত্ক্ষণিক asList (উপাদানসমূহ) থেকে অন্তর্নিহিত তালিকা টস করার পরিবর্তে একটি লুপ ব্যবহার করব:

static public Set<T> setOf(T ... elements) {
    Set set=new HashSet<T>(elements.size());
    for(T elm: elements) { set.add(elm); }
    return set;
    }

1
কেন? নতুন অবজেক্টটি এডেন স্পেসে তৈরি করা হবে এবং তাই কেবল ইনস্ট্যান্ট করতে দুটি বা তিনটি পয়েন্টার সংযোজন প্রয়োজন। জেভিএম লক্ষ্য করতে পারে যে এটি কখনই পদ্ধতির সুযোগ ছাড়িয়ে যায় না এবং তাই স্ট্যাকের উপর বরাদ্দ করে।
নাট

হ্যাঁ, এটি সম্ভবত কোডটির চেয়ে বেশি দক্ষ হয়ে উঠবে (যদিও আপনি HashSetপ্রস্তাবিত ক্ষমতা বলার মাধ্যমে এটি উন্নত করতে পারেন - লোড ফ্যাক্টরটি মনে রাখবেন)।
টম হাটিন -

ঠিক আছে, হ্যাশসেট কনস্ট্রাক্টরকে যাইহোক পুনরাবৃত্তি করতে হবে, সুতরাং এটি কম দক্ষ হবে না । পুনঃব্যবহারের জন্য তৈরি করা লাইব্রেরি কোডটি সর্বদা সর্বোত্তম সম্ভাব্য হওয়ার চেষ্টা করা উচিত ।
লরেন্স ডল

3

যদিও এই বাক্য গঠনটি সুবিধাজনক হতে পারে তবে এটি ested 0 উল্লেখগুলি যুক্ত করে কারণ এগুলি নেস্টেড হয়ে যায় এবং প্রতিটিটিতে ব্রেকপয়েন্ট নির্ধারণ না করা হলে আরম্ভকারীদের মধ্যে ডিবাগের পদক্ষেপ নেওয়া কঠিন হতে পারে। সেই কারণে, আমি কেবল এটি ব্যালাল সেটারগুলির জন্য ব্যবহার করার পরামর্শ দিচ্ছি, বিশেষত ধ্রুবকদের জন্য সেট করুন এবং এমন জায়গাগুলি যেখানে বেনাম সাবক্লাসগুলি কোনও বিষয় নয় (যেমন সিরিয়ালকরণ জড়িত নয়)।


3

মারিও গ্লেইচম্যান স্কেল লিস্টের আক্ষরিক অনুকরণের জন্য জাভা 1.5 জেনেরিক ফাংশন কীভাবে ব্যবহার করবেন তা বর্ণনা করেছেন , যদিও দুর্ভাগ্যক্রমে আপনি অপরিবর্তনীয় তালিকাগুলি সরিয়ে ।

তিনি এই শ্রেণীর সংজ্ঞা দিয়েছেন:

package literal;

public class collection {
    public static <T> List<T> List(T...elems){
        return Arrays.asList( elems );
    }
}

এবং এটি এভাবে ব্যবহার করে:

import static literal.collection.List;
import static system.io.*;

public class CollectionDemo {
    public void demoList(){
        List<String> slist = List( "a", "b", "c" );
        List<Integer> iList = List( 1, 2, 3 );
        for( String elem : List( "a", "java", "list" ) )
            System.out.println( elem );
    }
}

গুগল সংগ্রহ, এখন পেয়ারা অংশ তালিকার নির্মাণের জন্য অনুরূপ ধারণা সমর্থন করে। ইন এই সাক্ষাতকারের , জ্যারেড লেভি বলেছেন:

[...] সর্বাধিক ভারী ব্যবহৃত বৈশিষ্ট্যগুলি, যা আমি লিখি প্রায় প্রতিটি জাভা ক্লাসে প্রদর্শিত হয়, হ'ল স্থির পদ্ধতি যা আপনার জাভা কোডে পুনরাবৃত্তি কীস্ট্রোকের সংখ্যা হ্রাস করে। নিম্নলিখিতগুলির মতো কমান্ড প্রবেশ করতে সক্ষম হওয়া এত সুবিধাজনক:

Map<OneClassWithALongName, AnotherClassWithALongName> = Maps.newHashMap();

List<String> animals = Lists.immutableList("cat", "dog", "horse");

7/10/2014: কেবলমাত্র পাইথনের মতোই এটি সহজ হতে পারে:

animals = ['cat', 'dog', 'horse']

2/21/2020: জাভা 11 এ আপনি এখন বলতে পারেন:

animals = List.of(“cat”, “dog”, “horse”)


2
  1. এটি add()প্রতিটি সদস্যের জন্য কল করবে । আপনি যদি হ্যাশ সেটে আইটেমগুলি রাখার আরও কার্যকর উপায় খুঁজে পেতে পারেন তবে তা ব্যবহার করুন। নোট করুন যে অভ্যন্তরীণ বর্গটি সম্ভবত আবর্জনা তৈরি করবে, যদি আপনি সে সম্পর্কে সংবেদনশীল হন।

  2. আমার কাছে মনে হয় যেন প্রসঙ্গটি সেই বস্তুর দ্বারা ফিরে আসে new, যা এটি HashSet

  3. আপনার যদি জিজ্ঞাসা করা দরকার ... আরও সম্ভবত: আপনার পরে আসা লোকেরা কি এটি জানবে বা জানবে না? এটা বোঝা এবং ব্যাখ্যা করা সহজ? যদি আপনি উভয়কে "হ্যাঁ" উত্তর দিতে পারেন তবে এটি নির্দ্বিধায় ব্যবহার করুন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.