স্পার্সআরে বনাম হ্যাশম্যাপ


177

আমি HashMapপূর্ণসংখ্যার কীগুলির সাথে SparseArrayএস এর চেয়ে আরও ভাল কারণগুলির বেশ কয়েকটি কারণ সম্পর্কে ভাবতে পারি :

  1. একটির জন্য অ্যান্ড্রয়েড ডকুমেন্টেশন SparseArrayবলে "এটি সাধারণত একটি traditionalতিহ্যবাহী তুলনায় ধীর HashMap"।
  2. যদি আপনি কোডগুলি HashMaps এর পরিবর্তে কোড ব্যবহার করে লিখেন তবে SparseArrayআপনার কোড মানচিত্রের অন্যান্য প্রয়োগের সাথে কাজ করবে এবং আপনি মানচিত্রের জন্য ডিজাইন করা সমস্ত জাভা এপিআই ব্যবহার করতে সক্ষম হবেন।
  3. আপনি যদি HashMapএস এর পরিবর্তে এস ব্যবহার করে কোড লিখেন তবে SparseArrayআপনার কোডটি অ অ্যান্ড্রয়েড প্রকল্পগুলিতে কাজ করবে।
  4. মানচিত্র ওভাররাইড করে equals()এবং hashCode()যেখানে SparseArrayহয় না।

তবুও যখনই আমি HashMapকোনও অ্যান্ড্রয়েড প্রকল্পে পূর্ণসংখ্যা কী সহ একটি ব্যবহার করার চেষ্টা করি , ইন্টেলিজ আমাকে বলে যে SparseArrayতার পরিবর্তে আমার ব্যবহার করা উচিত । আমি বুঝতে এটি সত্যই কঠিন মনে করি। কেউ কি SparseArrayএস ব্যবহারের কোনও বাধ্যতামূলক কারণ জানেন ?

উত্তর:


235

SparseArrayHashMapকীটি কোনও আদিম ধরণের হলে প্রতিস্থাপন করতে ব্যবহার করা যেতে পারে । বিভিন্ন কী / মান প্রকারের জন্য কিছু বৈকল্পিক রয়েছে, যদিও সেগুলি সমস্ত প্রকাশ্যে উপলব্ধ নয়।

উপকারিতা হ'ল:

  • বরাদ্দ মুক্ত
  • কোন বক্সিং

অপূর্ণতা:

  • সাধারণত ধীর, বড় সংগ্রহের জন্য নির্দেশিত নয়
  • তারা অ-অ্যান্ড্রয়েড প্রকল্পে কাজ করবে না

HashMap নিম্নলিখিত দ্বারা প্রতিস্থাপন করা যেতে পারে:

SparseArray          <Integer, Object>
SparseBooleanArray   <Integer, Boolean>
SparseIntArray       <Integer, Integer>
SparseLongArray      <Integer, Long>
LongSparseArray      <Long, Object>
LongSparseLongArray  <Long, Long>   //this is not a public class                                 
                                    //but can be copied from  Android source code 

মেমরি নিরিখে এখানে একটি উদাহরণ SparseIntArrayবনাম HashMap<Integer, Integer>1000 উপাদানের জন্য:

SparseIntArray:

class SparseIntArray {
    int[] keys;
    int[] values;
    int size;
}

শ্রেণি = 12 + 3 * 4 = 24 বাইট
অ্যারে = 20 + 1000 * 4 = 4024 বাইট
মোট = 8,072 বাইট

HashMap:

class HashMap<K, V> {
    Entry<K, V>[] table;
    Entry<K, V> forNull;
    int size;
    int modCount;
    int threshold;
    Set<K> keys
    Set<Entry<K, V>> entries;
    Collection<V> values;
}

শ্রেণি = 12 + 8 * 4 = 48 বাইট
এন্ট্রি = 32 + 16 + 16 = 64 বাইট
অ্যারে = 20 + 1000 * 64
= 64024 বাইট মোট = 64,136 বাইট

উত্স: 90 স্লাইড থেকে রোমেন গাইয়ের অ্যান্ড্রয়েড স্মৃতি

উপরের নম্বরগুলি হ'ল জেভিএম দ্বারা স্তূপিত বরাদ্দকৃত মেমরির পরিমাণ (বাইটে)। এগুলি ব্যবহৃত নির্দিষ্ট জেভিএমের উপর নির্ভর করে পরিবর্তিত হতে পারে।

java.lang.instrumentপ্যাকেজের সাথে একটি বস্তুর আকার চেক মত উন্নত অপারেশনের জন্য কিছু সহায়ক পদ্ধতি রয়েছে getObjectSize(Object objectToSize)

অতিরিক্ত তথ্য অফিসিয়াল ওরাকল ডকুমেন্টেশন থেকে উপলব্ধ ।

শ্রেণি = 12 বাইট + (n উদাহরণ ভেরিয়েবল) * 4 বাইট
অ্যারে = 20 বাইট + (এন উপাদানসমূহ) * (উপাদান আকার)
প্রবেশিকা = 32 বাইট + (প্রথম উপাদান আকার) + (২ য় উপাদান আকার)


15
সেই "12 + 3 * 4" এবং "20 + 1000 * 4" কোথা থেকে এসেছে কেউ আমাকে গাইড করতে পারে?
মেরিয়ান প্যাডজিওচ

5
@ মারিয়ানপাডজিওচ, তিনি একটি উপস্থাপনা দেখিয়েছিলেন ( স্পিকারডেক.com / রোমাইংইউ / অ্যান্ড্রয়েড-মেমরিস ) যেখানে কোনও শ্রেণি 12 বাইট + 3 4 বাইটের ভেরিয়েবল দখল করে, একটি অ্যারে (রেফারেন্স) 20 বাইট (ডিএলম্লোক - 4, অবজেক্ট ওভারহেড - 8, প্রস্থ এবং প্যাডিং) দখল করে - 8)।
কুলমাইন্ড

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

@ ডেভিডজি আপনি অ্যান্ড্রয়েড নির্ভরতাগুলি উপহাস করার জন্য আনমক প্লাগইনটি ব্যবহার করতে পারেন ।
বরফখণ্ড

1
এমনকি যদি আপনি অ্যান্ড্রয়েড না করেন তবে ক্লাসটি আপনার প্রকল্পে অনুলিপি করা শক্ত নয়, এটি কেবলমাত্র 3 অন্যান্য শ্রেণীর উপর নির্ভর করে। এপিএল লাইসেন্স মানে এটি করা ঠিক আছে, আপনি যে লাইসেন্সের সাথে কাজ করছেন।
ইয়ান টিএম

35

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

একটি স্পার্সআরে তৈরি করুন

SparseArray<String> sparseArray = new SparseArray<>();

একটি SparseArrayমানচিত্র কারও কারও সাথে পূর্ণসংখ্যার সাথে যুক্ত হয় Object, যাতে আপনি Stringউপরের উদাহরণটিতে অন্য কোনওটির সাথে প্রতিস্থাপন করতে পারেন Object। আপনি যদি পূর্ণসংখ্যায় পূর্ণসংখ্যার মানচিত্র তৈরি করেন তবে ব্যবহার করুন SparseIntArray

আইটেমগুলি যুক্ত বা আপডেট করুন

অ্যারেতে উপাদান যুক্ত করতে put(বা append) ব্যবহার করুন।

sparseArray.put(10, "horse");
sparseArray.put(3, "cow");
sparseArray.put(1, "camel");
sparseArray.put(99, "sheep");
sparseArray.put(30, "goat");
sparseArray.put(17, "pig");

মনে রাখবেন intকীগুলি ক্রমযুক্ত হওয়ার দরকার নেই। এটি কোনও নির্দিষ্ট intকীতে মান পরিবর্তন করতেও ব্যবহার করা যেতে পারে ।

আইটেমগুলি সরান

অ্যারে থেকে উপাদানগুলি সরাতে remove(বা delete) ব্যবহার করুন ।

sparseArray.remove(17); // "pig" removed

intপরামিতি পূর্ণসংখ্যা চাবিকাঠি।

কোন কী কীর জন্য অনুসন্ধানের মান

getকিছু সংখ্যক কীটির মান পেতে ব্যবহার করুন ।

String someAnimal = sparseArray.get(99);  // "sheep"
String anotherAnimal = sparseArray.get(200); // null

আপনি কী কী হারিয়েছেন get(int key, E valueIfKeyNotFound)তা এড়াতে চাইলে আপনি ব্যবহার করতে পারেন null

আইটেমগুলির উপরে আইট্রেট করুন

সংগ্রহটি লুপ করতে আপনি keyAtএবং valueAtকিছু সূচক ব্যবহার করতে পারেন কারণ কীগুলি SparseArrayথেকে পৃথক সূচি বজায় রাখে int

int size = sparseArray.size();
for (int i = 0; i < size; i++) {

    int key = sparseArray.keyAt(i);
    String value = sparseArray.valueAt(i);

    Log.i("TAG", "key: " + key + " value: " + value);
}

// key: 1 value: camel
// key: 3 value: cow
// key: 10 value: horse
// key: 30 value: goat
// key: 99 value: sheep

নোট করুন যে কীগুলি ক্রমবর্ধমান মান অনুসারে অর্ডার করা হয়, সেগুলি যে ক্রমে যুক্ত হয়েছিল সেভাবে নয়।


18

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

এটির এই দস্তাবেজ থেকে কেবল একটি সতর্কতা হ'ল বিচ্ছিন্ন অ্যারে:

এটি অবজেক্ট টু অবজেক্টস মানচিত্রের জন্য হ্যাশম্যাপ ব্যবহারের চেয়ে বেশি মেমরির দক্ষ হওয়ার উদ্দেশ্যে is

SparseArrayহতে তৈরি করা হয় দক্ষ মেমরির নিয়মিত HashMap ব্যবহার করার পরিবর্তে, যে HashMap মত নয় অ্যারের মধ্যে একাধিক ফাঁক অনুমতি দেয় না। ডিভাইসে মেমরি বরাদ্দের বিষয়ে উদ্বিগ্ন না হওয়ার ইচ্ছে থাকলে আপনি traditionalতিহ্যবাহী হ্যাশম্যাপটি ব্যবহার করতে পারেন এটি নিয়ে চিন্তার কিছু নেই।


5
মেমরি সংরক্ষণের বিষয়গুলি স্পষ্টতই বৈধ, তবে অ্যান্ড্রয়েড কেন স্পার্সআরে <T> মানচিত্র <পূর্ণসংখ্যা, টি> প্রয়োগ করতে পারে না তা বুঝতে পারি নি যাতে আপনি একটি মেমরি দক্ষ মানচিত্র প্রয়োগ করতে পারেন - উভয় বিশ্বের সেরা।
পল বোডিংটন

3
@ পোলবডিংটন এছাড়াও মনে রাখবেন SparseArrayকী পূর্ণসংখ্যাকে অটো বক্স হতে বাধা দেয় যা অন্য অপারেশন এবং ব্যয় সম্পাদন। মানচিত্রের পরিবর্তে এটি আদিম পূর্ণসংখ্যার সাথে অটোবক্স করবেInteger
রড_এলগনকুইন

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

6
@ পলবডিংটন সংগ্রহগুলি এমন বস্তুর উপর ভিত্তি করে তৈরি করা হয়েছে যেগুলি আদিম নয় তাই এটি সংগ্রহের এপিআইয়ের মধ্যে কাজ করবে না
রড_আলগনকুইন

10

জাভাতে একটি স্পার্স অ্যারে এমন একটি ডেটা স্ট্রাকচার যা মানগুলির কীগুলি ম্যাপ করে। মানচিত্র হিসাবে একই ধারণা, তবে বিভিন্ন বাস্তবায়ন:

  1. একটি মানচিত্র তালিকার একটি অ্যারে হিসাবে অভ্যন্তরীণভাবে উপস্থাপিত হয়, যেখানে এই তালিকাগুলির প্রতিটি উপাদান একটি মূল, মান জোড়। কী এবং মান উভয়ই বস্তুর দৃষ্টান্ত।

  2. একটি স্পারস অ্যারে কেবল দুটি অ্যারে দিয়ে তৈরি হয়: (আদিম) কীগুলির অ্যারে এবং (অবজেক্ট) মানগুলির একটি অ্যারে। এই অ্যারে সূচকগুলিতে ফাঁক থাকতে পারে, সুতরাং "স্পার্স" অ্যারে শব্দটি term

স্পারসারির প্রধান আগ্রহ হ'ল এটি কী হিসাবে বস্তুর পরিবর্তে আদিম ব্যবহার করে স্মৃতি সংরক্ষণ করে memory


10

কিছু গুগল করার পরে আমি ইতিমধ্যে পোস্ট করা উত্তরগুলিতে কিছু তথ্য যুক্ত করার চেষ্টা করি:

আইজ্যাক টেলর স্পার্সআরাই এবং হ্যাশম্যাপসের জন্য পারফরম্যান্স তুলনা করেছেন। তিনি বলেছেন যে

ডাবল স্ট্রাকচার আকারের জন্য 1000 এর নীচে হ্যাশম্যাপ এবং স্পার্সআরে খুব মিল

এবং

যখন আকারটি 10,000 মার্কে উন্নীত করা হয়েছে [...] হ্যাশম্যাপে অবজেক্ট যুক্ত করার সাথে আরও বেশি পারফরম্যান্স রয়েছে, যখন স্পার্সআর্রিতে অ্যাক্টেসগুলি পুনরুদ্ধার করার সময় আরও বেশি কর্মক্ষমতা রয়েছে has [...] ১০,০০,০০০ আকারে [...] হ্যাশম্যাপ খুব দ্রুত পারফরম্যান্স হারিয়ে ফেলে

এডজব্লগের সাথে একটি তুলনা দেখায় যে একটি স্পার্সআরে হ্যাশম্যাপের তুলনায় অনেক কম স্মৃতি দরকার যা ছোট কী (ইন্ট বনাম পূর্ণসংখ্যার) এবং এই কারণে

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

উপসংহার হিসাবে আমি বলব যে আপনি যদি নিজের মানচিত্রে প্রচুর ডেটা সঞ্চয় করতে যাচ্ছেন তবে পার্থক্যটি বিবেচনা করতে পারে। অন্যথায়, কেবল সতর্কতা উপেক্ষা করুন।


4

স্পারসারির জন্য অ্যান্ড্রয়েড ডকুমেন্টেশন বলে যে "এটি সাধারণত একটি traditionalতিহ্যবাহী হ্যাশম্যাপের চেয়ে ধীর"।

হ্যাঁ এটা ঠিক. তবে যখন আপনার কাছে কেবল 10 বা 20 টি আইটেম রয়েছে, পারফরম্যান্সের পার্থক্যটি নগণ্য হওয়া উচিত।

আপনি যদি স্পার্সআর্রাইয়ের পরিবর্তে হ্যাশম্যাপগুলি ব্যবহার করে কোড লিখেন তবে আপনার কোড মানচিত্রের অন্যান্য প্রয়োগের সাথে কাজ করবে এবং আপনি মানচিত্রের জন্য নকশা করা জাভা এপিআইয়ের সমস্ত ব্যবহার করতে সক্ষম হবেন

আমি মনে করি বেশিরভাগ ক্ষেত্রে আমরা কেবল HashMapকোনও কীটির সাথে সম্পর্কিত একটি মান সন্ধান করতে ব্যবহার করি যখন এতে SparseArrayসত্যই ভাল হয়।

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

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

মানচিত্র সমান () এবং হ্যাশকোড () এর ওভাররাইড করে যেখানে স্পার্সআর্রে হয় না

আমি কেবল বলতে পারি, (বেশিরভাগ বিকাশকারীদের) কে যত্ন করে?

আরেকটি গুরুত্বপূর্ণ দিক SparseArrayএটি শুধুমাত্র যখন সব উপাদান সেভ করার জন্য Array ব্যবহার করে HashMapব্যবহারসমূহ Entry, তাই SparseArrayএকটি চেয়ে উল্লেখযোগ্য কম মেমরি খরচ HashMapদেখুন এই


1

দুর্ভাগ্যজনক যে সংকলকটি একটি সতর্কতা জারি করেছে। আমার ধারণা হ্যাশম্যাপ আইটেমগুলি সংরক্ষণের জন্য অতিরিক্তভাবে ব্যবহৃত হয়েছে।

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

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

আমি আপনাকে পরামর্শ দিচ্ছি যে যদি আপনার একটি হ্যাশ টেবিলের প্রয়োজন হয় এবং আদিম পূর্ণসংখ্যার (অটো বক্সিং নয়) ইত্যাদির জন্য আরও ভাল মেমরি ব্যবহার করতে চান তবে ট্রভ চেষ্টা করুন। ( http://trove.starlight-systems.com - এলজিপিএল লাইসেন্স)। (তাদের লাইব্রেরির মতো ট্রোভের সাথে কোনও সম্পর্ক নেই)

সরলিকৃত মাল্টি-ডেক্স বিল্ডিংয়ের সাথে আমাদের আপনার প্রয়োজনের জন্য ট্র্যাভের পুনঃকেজ করার দরকার নেই। (ট্রোভের অনেক ক্লাস রয়েছে)

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