একটি সেট থেকে একটি উপাদান পাওয়া


322

Setঅন্য উপাদানটির সমান একটি উপাদান পেতে কেন কোনও ক্রিয়াকলাপ সরবরাহ করে না ?

Set<Foo> set = ...;
...
Foo foo = new Foo(1, 2, 3);
Foo bar = set.get(foo);   // get the Foo element from the Set that equals foo

আমি জিজ্ঞাসা করতে পারি যে Setএতে উপাদানগুলির সমান উপাদান রয়েছে কিনা barতাই আমি কেন সেই উপাদানটি পেতে পারি না? :(

স্পষ্ট করার জন্য, equalsপদ্ধতিটি ওভাররাইড করা হয়েছে তবে এটি কেবল একটি ক্ষেত্রই পরীক্ষা করে, সমস্তটি নয়। সুতরাং দুটি Fooবস্তু যে সমান বিবেচিত হয় আসলে বিভিন্ন মান থাকতে পারে, এজন্য আমি কেবল ব্যবহার করতে পারি না foo


2
এই পোস্টটি ইতিমধ্যে ব্যাপকভাবে আলোচনা করা হয়েছে, এবং ভাল উত্তর প্রস্তাব দেওয়া হয়েছে। তবে আপনি যদি কেবল কোনও অর্ডারযুক্ত সেট সন্ধান করছেন, কেবল ব্যবহার করুন SortedSetএবং এর প্রয়োগগুলি, যা মানচিত্র ভিত্তিক (যেমন TreeSetঅ্যাক্সেসের অনুমতি দেয় first())।
এলিরান মালকা

3
আপনি উপরে বর্ণিত ঠিক একই ক্ষেত্রে আমিও সেই পদ্ধতিটি মিস করছি। উদ্দেশ্য-সি ( NSSet) এর এমন একটি পদ্ধতি রয়েছে such একে বলা হয় memberএবং এটি সেটের মধ্যে থাকা বস্তুটি প্রদান করে memberযা পদ্ধতির প্যারামিটারের সাথে "সমান" তুলনা করে (যা অবশ্যই পৃথক বস্তু হতে পারে এবং বিভিন্ন বৈশিষ্ট্যও থাকতে পারে, এটি সমান চেক করতে পারে না)।
মক্কি

উত্তর:


118

এটি সমান হলে উপাদানটি পাওয়ার কোনও লাভ নেই। এ Mapএই ইউসকেসটির জন্য আরও ভাল।


আপনি যদি এখনও উপাদানটি সন্ধান করতে চান তবে আপনার কাছে পুনরাবৃত্তকারী ব্যবহার করা ছাড়া অন্য কোনও বিকল্প নেই:

public static void main(String[] args) {

    Set<Foo> set = new HashSet<Foo>();
    set.add(new Foo("Hello"));

    for (Iterator<Foo> it = set.iterator(); it.hasNext(); ) {
        Foo f = it.next();
        if (f.equals(new Foo("Hello")))
            System.out.println("foo found");
    }
}

static class Foo {
    String string;
    Foo(String string) {
        this.string = string;
    }
    @Override
    public int hashCode() { 
        return string.hashCode(); 
    }
    @Override
    public boolean equals(Object obj) {
        return string.equals(((Foo) obj).string);
    }
}

234
উপাদানটি পেতে একেবারে একটি বিষয় হতে পারে। আপনি যদি ইতিমধ্যে সেটটিতে যোগ করার পরে কোনও উপাদানটির মানগুলির কিছু আপডেট করতে চান? উদাহরণস্বরূপ, যখন .equals () সমস্ত ক্ষেত্র ব্যবহার করে না, যেমন ওপি নির্দিষ্ট করেছে। একটি কম দক্ষ সমাধান হ'ল উপাদানটি সরিয়ে ফেলা এবং তার মানগুলি আপডেট হওয়া সাথে এটি পুনরায় যুক্ত করা।
কাইলিম

14
আমি এখনও তর্ক করব যে একটি Mapআরও ভাল উপযুক্ত ( Map<Foo, Foo>এই ক্ষেত্রে
dacwe

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

4
@ কাইলিম আমি ব্যবহারের বিষয়টি বুঝতে পেরেছি, তবে আমি হ্যাশকোড / সমান অংশগুলির স্পর্শযোগ্য বৈশিষ্ট্যগুলির স্পর্শ না করার গুরুত্বকে গুরুত্ব দিতে চাই। সেট জাভাদোক থেকে: "দ্রষ্টব্য: যদি পরিবর্তনীয় বস্তুগুলি সেট উপাদান হিসাবে ব্যবহার করা হয় তবে অবশ্যই দুর্দান্ত যত্ন নেওয়া উচিত an বস্তুর মানটি এমনভাবে পরিবর্তিত হয় যা বস্তুর সাথে সমান তুলনাকে প্রভাবিত করে সেটে উপাদান। " - আমি সেই জিনিসগুলিকে অপরিবর্তনীয় হতে বা কমপক্ষে অপরিবর্তনীয় মূল গুণাবলী থাকার পরামর্শ দিই।
স্টিভ্লো

5
আমি সম্মত হয়েছি যে আপনি Map<Foo, Foo>প্রতিস্থাপন হিসাবে ব্যবহার করতে পারেন , অবনমনটি হ'ল মানচিত্রে সর্বদা কমপক্ষে একটি কী এবং একটি মান (এবং কার্য সম্পাদনের জন্য এটি হ্যাশও সঞ্চয় করা উচিত) রাখতে হবে, যখন একটি সেট কেবল মান সংরক্ষণ করে চলে যেতে পারে (এবং পারফরম্যান্সের জন্য সম্ভবত হ্যাশ)। সুতরাং একটি ভাল সেট বাস্তবায়ন সমান দ্রুত হতে পারে Map<Foo, Foo>তবে 50% কম মেমরি ব্যবহার করতে পারে। জাভার ক্ষেত্রে এটি কোনও ব্যাপার নয়, কারণ হ্যাশসেটটি অভ্যন্তরীণভাবে হ্যাশম্যাপের উপর ভিত্তি করে।
মক্কি

372

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

এখন অন্তর্নিহিত প্রশ্নের "আপনি কীভাবে তখন উপাদানটি পাবেন": আমি মনে করি যে উপাদানগুলি নিজের কাছে মানচিত্রের জন্য একটি এর Map<E,E>পরিবর্তে একটি ব্যবহার করা ভাল সমাধান Set<E>। এইভাবে, আপনি দক্ষতার সাথে "সেট" থেকে কোনও উপাদান পুনরুদ্ধার করতে পারেন , কারণ উইন্ডোজের get () পদ্ধতিটি Mapএকটি দক্ষ হ্যাশ টেবিল বা ট্রি অ্যালগোরিদম ব্যবহার করে উপাদানটি খুঁজে পাবে। আপনি চান, তাহলে আপনি আপনার নিজস্ব বাস্তবায়ন লিখতে পারে Setঅফার করে অতিরিক্ত get()পদ্ধতি, encapsulating Map

নিম্নলিখিত উত্তরগুলি আমার মতে খারাপ বা ভুল:

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

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


27
Meh। সমানদের বাস্তবায়নকে ওভাররাইড করা যাতে অ-সম-বস্তুগুলি "সমান" হয় তা এখানে সমস্যা। এমন একটি পদ্ধতির জন্য জিজ্ঞাসা করুন যা বলছে "আমাকে এই বস্তুর মতো অভিন্ন বস্তুটি পান" এবং তারপরে কোনও অ-অভিন্ন বস্তুটি প্রত্যাবর্তনের প্রত্যাশা পাগল এবং রক্ষণাবেক্ষণের সমস্যার কারণ হতে পারে বলে মনে হয়। অন্যরা যেমন পরামর্শ দিয়েছে, মানচিত্র ব্যবহার করা এই সমস্ত সমস্যার সমাধান করে: এবং এটি আপনি যা করছেন তা স্বতঃব্যক্তিকর করে তোলে। এটি সহজেই বোঝা যায় যে দুটি মানহীন-সমান অবজেক্টের মানচিত্রে একই কী থাকতে পারে এবং একই কী থাকলে তাদের মধ্যকার সম্পর্ক প্রদর্শিত হবে।
ডেভিড ওগ্রেন

20
শক্তিশালী শব্দ, @ ডেভিড ওগ্রেন। সাধরণ? ক্রেজি? তবে আপনার মন্তব্যে আপনি "অভিন্ন" এবং "সমান" শব্দটি ব্যবহার করছেন যেন তারা একই জিনিস বোঝায়। তারা করে নাই. বিশেষত, জাভাতে, পরিচয়টি "==" অপারেটর দ্বারা প্রকাশ করা হয় এবং সমতা সমান () পদ্ধতি দ্বারা প্রকাশ করা হয়। যদি তারা একই জিনিস বোঝায় তবে কোনও সমতুল্য () পদ্ধতির প্রয়োজন হবে না। অন্যান্য ভাষায়, এটি অবশ্যই আলাদা হতে পারে। উদাহরণস্বরূপ, গ্রোভিতে পরিচয় হ'ল () পদ্ধতি এবং সমতা "=="। মজার, তাই না?
jschreiner

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

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

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

19

আপনার যদি সমান অবজেক্ট থাকে তবে সেট থেকে কেন আপনার দরকার? যদি এটি কেবল কোনও কী দ্বারা "সমান" হয় Mapতবে একটি ভাল পছন্দ হবে।

যাইহোক, নিম্নলিখিতগুলি এটি করবে:

Foo getEqual(Foo sample, Set<Foo> all) {
  for (Foo one : all) {
    if (one.equals(sample)) {
      return one;
    }
  } 
  return null;
}

জাভা 8 এর মাধ্যমে এটি ওয়ান লাইনারে পরিণত হতে পারে:

return all.stream().filter(sample::equals).findAny().orElse(null);

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

8
@ লিও ধন্যবাদ, তবে একক প্রস্থান দৃষ্টান্তটি ওওপির বিপরীতে নয় এবং ফোর্টরান বা সিওবিএল এর চেয়ে আধুনিক ভাষাগুলির জন্য বেশিরভাগ ক্ষেত্রেই অবৈধ, এছাড়াও সফ্টওয়্যারেনজিনিয়ারিং.স্ট্যাকেক্সেঞ্জঞ্জ
আর্ন বার্মিস্টার

1
কোনও সেটের পরিবর্তে মানচিত্র ব্যবহার করা আরও ভাল বিকল্প বলে মনে হয়: কোনও সেটের উপাদানগুলির উপর পুনরাবৃত্তি মানচিত্রের থেকে একক মান পাওয়ার চেয়ে বেশি কাজ। (ও (এন) বনাম ও (1))
জেমি ফ্লোরনয়

@ জামিফ্লোরনয় ঠিক আছে, যদি আপনাকে বিভিন্ন উপাদানগুলির জন্য একই সেটটি একাধিকবার পরীক্ষা করতে হয় তবে এটি আরও ভাল। একক ব্যবহারের জন্য নয়, কারণ এটির জন্য প্রথমে মানচিত্রটি তৈরি করতে আরও প্রচেষ্টা প্রয়োজন।
অর্ণ বার্মিস্টার 21

18

তালিকাতে সেট রূপান্তর করুন এবং তারপরে getতালিকার পদ্ধতিটি ব্যবহার করুন

Set<Foo> set = ...;
List<Foo> list = new ArrayList<Foo>(set);
Foo obj = list.get(0);

37
আমি এই না। এটি সেটের একটি স্বেচ্ছাচারিত বস্তু পুনরুদ্ধার করবে । না অবজেক্ট।
আইয়ুব

14

জাভাতে ডিফল্ট সেটটি দুর্ভাগ্যক্রমে jschreiner হিসাবে "get" অপারেশন সরবরাহ করার জন্য ডিজাইন করা হয়নি সঠিকভাবে ব্যাখ্যা করার সাথে সাথে ।

আগ্রহের উপাদানটি আবিষ্কার করার জন্য একটি আইট্রেটর ব্যবহার করার সমাধানগুলি ( ড্যাকউ দ্বারা প্রস্তাবিত ) অথবা উপাদানটি সরিয়ে পুনরায় যুক্ত করতে এটির মানগুলি আপডেট হয়েছে ( কাইলেম দ্বারা প্রস্তাবিত ) ) হতে পারে, তবে খুব অদক্ষ হতে পারে।

সমানদের বাস্তবায়নকে ওভাররাইড করা যাতে অ-সম-বস্তুগুলি "সমান" হয়, যেমন ডেভিড ওগ্রেন সঠিকভাবে বলেছেন সহজেই রক্ষণাবেক্ষণের সমস্যা তৈরি করতে পারে।

এবং একটি মানচিত্রকে সুস্পষ্ট প্রতিস্থাপন হিসাবে (অনেকের পরামর্শ অনুসারে) ব্যবহার করা কোডটি কম মার্জিত করে তোলে।

যদি লক্ষ্যটি সেটটিতে থাকা উপাদানটির আসল উদাহরণটি অ্যাক্সেস করা হয় (আশা করি আমি আপনার ব্যবহারের বিষয়টি সঠিকভাবে বুঝতে পেরেছি), তবে এখানে আরও একটি সম্ভাব্য সমাধান রয়েছে।


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

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

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

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

তবে সরাসরি একই জাতীয় ব্যবহারের ক্ষেত্রে মানচিত্র ব্যবহার করা এখনও নিষ্ক্রিয় ছিল। কেউ তর্ক করতে পারে যে মানচিত্র ব্যবহার করা ম্যানটেন এবং হ্যান্ডেল করার ক্ষেত্রে আরও জটিল হতে পারে।

এই কারণে আমি ম্যাজিকসেট নামে একটি লাইব্রেরি প্রয়োগ করেছি, যা একটি মানচিত্রের ব্যবহারকে বিকাশকারীকে "স্বচ্ছ" করে তোলে।

https://github.com/ricpacca/magicset


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

তদুপরি, একটি ম্যাজিকসেটটি হুবহু সেট হিসাবে ব্যবহার করা যেতে পারে তবে আরও কিছু পদ্ধতির সাথে অতিরিক্ত ক্রিয়াকলাপ সরবরাহ করে যেমন getFromId (), popFromId (), সরানোফ্রিমআইডি () ইত্যাদি)

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


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

class City extends UniqueItem {

    // Somewhere in this class

    public void doSomething() {
        // Whatever
    }
}

public class GameMap {
    private MagicSet<City> cities;

    public GameMap(Collection<City> cities) {
        cities = new MagicHashSet<>(cities);
    }

    /*
     * cityId is the UUID of the city you want to retrieve.
     * If you have a copied instance of that city, you can simply 
     * call copiedCity.getId() and pass the return value to this method.
     */
    public void doSomethingInCity(UUID cityId) {
        City city = cities.getFromId(cityId);
        city.doSomething();
    }

    // Other methods can be called on a MagicSet too
}

11

যদি আপনার সেটটি আসলে NavigableSet<Foo>(যেমন একটি TreeSet) হয়, এবং Foo implements Comparable<Foo>আপনি ব্যবহার করতে পারেন

Foo bar = set.floor(foo); // or .ceiling
if (foo.equals(bar)) {
    // use bar…
}

(ইঙ্গিতটির জন্য @ এলিরান-মালকার মন্তব্যের জন্য ধন্যবাদ))


5
আমি যদি আমার কোডটি প্রাথমিকভাবে ভেবে দেখেছি যে আমি সম্পূর্ণ উন্মাদ হয়ে গেছি কেউ যদি আপত্তি না করে থাকে তবে এটি একটি দুর্দান্ত সমাধান হবে।
আদম

10

জাভা 8 এর মাধ্যমে আপনি এটি করতে পারেন:

Foo foo = set.stream().filter(item->item.equals(theItemYouAreLookingFor)).findFirst().get();

তবে সতর্কতা অবলম্বন করুন, .get () একটি NoSuchElementException নিক্ষেপ করুন, বা আপনি একটি alচ্ছিক আইটেমটি পরিচালনা করতে পারেন।


5
item->item.equals(theItemYouAreLookingFor)সংক্ষিপ্ত করা যেতে পারেtheItemYouAreLookingFor::equals
হেন্নো ভার্মিউলেন

5
Object objectToGet = ...
Map<Object, Object> map = new HashMap<Object, Object>(set.size());
for (Object o : set) {
    map.put(o, o);
}
Object objectFromSet = map.get(objectToGet);

আপনি যদি কেবলমাত্র এটি পান তবে এটি খুব কার্যকরী হবে না কারণ আপনি আপনার সমস্ত উপাদানকে লুপ করবেন তবে একটি বড় সেটটিতে একাধিক পুনরুদ্ধার করার সময় আপনি পার্থক্যটি লক্ষ্য করবেন।


5

কেন:

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

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

জাভাডক্স থেকে

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

কিভাবে:

এখন যে স্ট্রিমগুলি চালু করা হয়েছে তারা নিম্নলিখিতটি করতে পারেন

mySet.stream()
.filter(object -> object.property.equals(myProperty))
.findFirst().get();

2

অ্যারে ক্লাস ব্যবহার সম্পর্কে কী?

import java.util.Arrays;
import java.util.List;
import java.util.HashSet;
import java.util.Arrays;

public class MyClass {
    public static void main(String args[]) {
        Set mySet = new HashSet();
        mySet.add("one");
        mySet.add("two");
        List list = Arrays.asList(mySet.toArray());
        Object o0 = list.get(0);
        Object o1 = list.get(1);
        System.out.println("items " + o0+","+o1);
    }
}

আউটপুট:
আইটেম এক, দুই



1

আমি জানি, এটি অনেক আগে জিজ্ঞাসা করা হয়েছে এবং উত্তর দেওয়া হয়েছে, তবে যদি কেউ আগ্রহী হয় তবে আমার সমাধানটি এখানে দেওয়া হয়েছে - হ্যাশম্যাপের সহায়তায় কাস্টম সেট শ্রেণি:

http://pastebin.com/Qv6S91n9

আপনি সহজেই অন্যান্য সেট সেটগুলি কার্যকর করতে পারেন।


7
এটি কেবল একটির সাথে সংযোগ স্থাপনের পরিবর্তে উদাহরণ অন্তর্ভুক্ত করা পছন্দ করে preferred
সমস্ত কর্মী

1

সেখানে হয়েছে !! আপনি যদি পেয়ারাটিকে কোনও মানচিত্রে রূপান্তর করার জন্য দ্রুত উপায় ব্যবহার করেন তা হ'ল:

Map<Integer,Foo> map = Maps.uniqueIndex(fooSet, Foo::getKey);

1

আপনি Iterator ক্লাস ব্যবহার করতে পারেন

import java.util.Iterator;
import java.util.HashSet;

public class MyClass {
 public static void main(String[ ] args) {
 HashSet<String> animals = new HashSet<String>();
animals.add("fox");
animals.add("cat");
animals.add("dog");
animals.add("rabbit");

Iterator<String> it = animals.iterator();
while(it.hasNext()) {
  String value = it.next();
  System.out.println(value);   
 }
 }
}

1

আপনি যদি হ্যাশসেট থেকে নবম এলিমেন্ট চান, আপনি নীচের সমাধান সহ যেতে পারেন, এখানে আমি হ্যাশসেটে মডেলক্লাসের অবজেক্ট যুক্ত করেছি।

ModelClass m1 = null;
int nth=scanner.nextInt();
for(int index=0;index<hashset1.size();index++){
    m1 = (ModelClass) itr.next();
    if(nth == index) {
        System.out.println(m1);
        break;
    }
}

1

আপনি যদি প্রয়োগের প্রথম কয়েকটি লাইন দেখে থাকেন তবে java.util.HashSetআপনি দেখতে পাবেন:

public class HashSet<E>
    ....
    private transient HashMap<E,Object> map;

সুতরাং যেকোন উপায়ে আন্তঃব্যক্তিকভাবে HashSetব্যবহার করে HashMapযার অর্থ আপনি যদি কেবলমাত্র একটি HashMapসরাসরি ব্যবহার করেন এবং কী এবং মান হিসাবে একই মান ব্যবহার করেন তবে আপনি নিজের পছন্দটি কার্যকর করতে পারেন এবং নিজেকে কিছুটা স্মৃতি সঞ্চয় করতে পারেন।


1

দেখে মনে হচ্ছে সঠিকভাবে ব্যবহারযোগ্য জিনিসটি হল পেয়ারা থেকে অভ্যন্তরীণ:

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

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


0

কারণ সেটের কোনও নির্দিষ্ট প্রয়োগ বাস্তবায়ন এলোমেলো অ্যাক্সেস হতে পারে বা নাও হতে পারে

আপনি সর্বদা একটি পুনরাবৃত্তকারী পেতে পারেন এবং সেটের মাধ্যমে পদক্ষেপ next()নিতে পারেন, পুনরাবৃত্তিকারীদের পদ্ধতিটি ব্যবহার করে আপনি একবার সমান উপাদানটি খুঁজে পাওয়ার পরে পুনরায় ফলাফলটি দেখতে চান return বাস্তবায়ন নির্বিশেষে এটি কাজ করে। যদি বাস্তবায়নটি এলোমেলো অ্যাক্সেস না হয় (চিত্রযুক্ত কোনও লিঙ্কযুক্ত তালিকার ব্যাক সেট করুন), get(E element)ইন্টারফেসের একটি পদ্ধতি প্রতারণামূলক হবে, যেহেতু উপাদানটি ফিরে আসার জন্য এটি সংগ্রহকে পুনরাবৃত্তি করতে হবে, এবং এর দ্বারা get(E element)এটি বোঝা যাবে প্রয়োজনীয়, সেট পেতে উপাদান সরাসরি লাফিয়ে যেতে পারে যে।

contains() অবশ্যই বাস্তবায়ন উপর নির্ভর করে একই জিনিস করতে হবে বা নাও করতে পারে, তবে নামটি একই ধরণের ভুল বোঝাবুঝির কাছে নিজেকে ধার দেবে বলে মনে হয় না।


2
Get () পদ্ধতিটি যা কিছু করবে তা ইতিমধ্যে () পদ্ধতি দ্বারা সম্পন্ন হচ্ছে। আপনি অন্তর্ভুক্ত থাকা বস্তুটি না পেয়ে এবং এর .equals () পদ্ধতিটি কল না করে () প্রয়োগ করতে পারবেন না। Java.util.List- এ একটি get () যোগ করার বিষয়ে এপিআই ডিজাইনারদের কোনও গুন নেই though যদিও কিছু প্রয়োগে এটি ধীর হবে।
ব্রায়ান রিঙ্ক

আমি এটা সত্য মনে করি না। দুটি অবজেক্ট সমান হয়ে সমান হতে পারে তবে == এর মাধ্যমে অভিন্ন নয়। আপনার যদি A, এবং একটি সেট এস, যা অবজেক্ট বি, এবং A.equals (B) কিন্তু A! = B রয়েছে এবং আপনি বিটির একটি রেফারেন্স পেতে চান, আপনি রেফারেন্স পেতে এসজেট (এ) কল করতে পারেন বি, ধরে নিচ্ছেন যে তালিকার গেট মেথডের শব্দার্থবিজ্ঞানের সাথে আপনার একটি গেট মেথড রয়েছে, যা এস সি কনটেনস (এ) (যা এটি হবে) যাচাই করার চেয়ে আলাদা ব্যবহারের ঘটনা। সংগ্রহের ক্ষেত্রে এটি ব্যবহারের ক্ষেত্রেও বিরল নয়।
টম ট্রেসানস্কি

0

হ্যাঁ, ব্যবহার করুন HashMap... তবে বিশেষায়িত উপায়ে: যে ছন্দটি আমি HashMapছদ্ম হিসাবে ব্যবহার করার চেষ্টা করেছিলাম - সেগুলির Set"প্রকৃত" উপাদান Map/Setএবং "প্রার্থী" উপাদানগুলির মধ্যে সম্ভাব্য বিভ্রান্তি , অর্থাৎ উপাদানগুলি পরীক্ষা করার জন্য ব্যবহৃত হয় কিনা equalউপাদান ইতিমধ্যে উপস্থিত। এটি নির্বোধ থেকে দূরে, তবে আপনাকে ফাঁদ থেকে দূরে সরিয়ে দেয়:

class SelfMappingHashMap<V> extends HashMap<V, V>{
    @Override
    public String toString(){
        // otherwise you get lots of "... object1=object1, object2=object2..." stuff
        return keySet().toString();
    }

    @Override
    public V get( Object key ){
        throw new UnsupportedOperationException( "use tryToGetRealFromCandidate()");
    }

    @Override
    public V put( V key, V value ){
       // thorny issue here: if you were indavertently to `put`
       // a "candidate instance" with the element already in the `Map/Set`: 
       // these will obviously be considered equivalent 
       assert key.equals( value );
       return super.put( key, value );
    }

    public V tryToGetRealFromCandidate( V key ){
        return super.get(key);
    }
}

তারপরে এটি করুন:

SelfMappingHashMap<SomeClass> selfMap = new SelfMappingHashMap<SomeClass>();
...
SomeClass candidate = new SomeClass();
if( selfMap.contains( candidate ) ){
    SomeClass realThing = selfMap.tryToGetRealFromCandidate( candidate );
    ...
    realThing.useInSomeWay()...
}

তবে ... আপনি এখন candidateকোনও উপায়ে আত্ম-বিনষ্ট করতে চান যদি না প্রোগ্রামার প্রকৃতপক্ষে তা অবিলম্বে রাখে Map/Set... আপনি contains"কলঙ্কিত" করতে চাইবেন candidateযাতে এটির সাথে যুক্ত না হওয়া পর্যন্ত এটির কোনও ব্যবহার Map"অ্যানথেমা" না করে "। সম্ভবত আপনি SomeClassএকটি নতুন Taintableইন্টারফেস বাস্তবায়ন করতে পারে ।

আরও সন্তোষজনক সমাধান নীচে যেমন একটি গেটেবল সেট । যাইহোক, এটি কাজ SomeClassকরার জন্য আপনাকে সমস্ত নির্মাতাকে অ-দৃশ্যমান করার জন্য (বা ... সক্ষম এবং এটির জন্য একটি র‌্যাপার ক্লাস ব্যবহার করতে সক্ষম) করার জন্য ডিজাইনের দায়িত্বে থাকতে হবে:

public interface NoVisibleConstructor {
    // again, this is a "nudge" technique, in the sense that there is no known method of 
    // making an interface enforce "no visible constructor" in its implementing classes 
    // - of course when Java finally implements full multiple inheritance some reflection 
    // technique might be used...
    NoVisibleConstructor addOrGetExisting( GettableSet<? extends NoVisibleConstructor> gettableSet );
};

public interface GettableSet<V extends NoVisibleConstructor> extends Set<V> {
    V getGenuineFromImpostor( V impostor ); // see below for naming
}

বাস্তবায়ন:

public class GettableHashSet<V extends NoVisibleConstructor> implements GettableSet<V> {
    private Map<V, V> map = new HashMap<V, V>();

    @Override
    public V getGenuineFromImpostor(V impostor ) {
        return map.get( impostor );
    }

    @Override
    public int size() {
        return map.size();
    }

    @Override
    public boolean contains(Object o) {
        return map.containsKey( o );
    }

    @Override
    public boolean add(V e) {
        assert e != null;
        V result = map.put( e,  e );
        return result != null;
    }

    @Override
    public boolean remove(Object o) {
        V result = map.remove( o );
        return result != null;
    }

    @Override
    public boolean addAll(Collection<? extends V> c) {
        // for example:
        throw new UnsupportedOperationException();
    }

    @Override
    public void clear() {
        map.clear();
    }

    // implement the other methods from Set ...
}

আপনার NoVisibleConstructorক্লাসগুলি তখন এর মতো দেখায়:

class SomeClass implements NoVisibleConstructor {

    private SomeClass( Object param1, Object param2 ){
        // ...
    }

    static SomeClass getOrCreate( GettableSet<SomeClass> gettableSet, Object param1, Object param2 ) {
        SomeClass candidate = new SomeClass( param1, param2 );
        if (gettableSet.contains(candidate)) {
            // obviously this then means that the candidate "fails" (or is revealed
            // to be an "impostor" if you will).  Return the existing element:
            return gettableSet.getGenuineFromImpostor(candidate);
        }
        gettableSet.add( candidate );
        return candidate;
    }

    @Override
    public NoVisibleConstructor addOrGetExisting( GettableSet<? extends NoVisibleConstructor> gettableSet ){
       // more elegant implementation-hiding: see below
    }
}

PS যেমন একটি NoVisibleConstructorশ্রেণীর সাথে একটি প্রযুক্তিগত সমস্যা : এটি আপত্তি করা যেতে পারে যে এই জাতীয় শ্রেণিটি সহজাতভাবে final, যা অনাকাঙ্ক্ষিত হতে পারে। আসলে আপনি সর্বদা একটি ডামি প্যারামিটারলেস protectedকনস্ট্রাক্টর যুক্ত করতে পারেন :

protected SomeClass(){
    throw new UnsupportedOperationException();
}

... যা কমপক্ষে একটি সাবক্লাস সংকলন করতে দেয়। এরপরে আপনাকে getOrCreate()সাবক্লাসে আরও একটি কারখানার পদ্ধতি অন্তর্ভুক্ত করতে হবে কিনা তা ভাবতে হবে ।

চূড়ান্ত পদক্ষেপ হ'ল একটি বিমূর্ত বেস ক্লাস (কোনও তালিকার জন্য এনবি "উপাদান", একটি সেটের জন্য "সদস্য") আপনার সেট সদস্যদের জন্য এটি (যখন সম্ভব হয় - আবার, যেখানে ক্লাসটি আপনার নিয়ন্ত্রণে নেই এমন একটি মোড়কের ক্লাস ব্যবহারের সুযোগ রয়েছে , বা ইতিমধ্যে একটি বেস ক্লাস ইত্যাদি রয়েছে), সর্বাধিক বাস্তবায়ন-আড়াল করার জন্য:

public abstract class AbstractSetMember implements NoVisibleConstructor {
    @Override
    public NoVisibleConstructor
            addOrGetExisting(GettableSet<? extends NoVisibleConstructor> gettableSet) {
        AbstractSetMember member = this;
        @SuppressWarnings("unchecked") // unavoidable!
        GettableSet<AbstractSetMembers> set = (GettableSet<AbstractSetMember>) gettableSet;
        if (gettableSet.contains( member )) {
            member = set.getGenuineFromImpostor( member );
            cleanUpAfterFindingGenuine( set );
        } else {
            addNewToSet( set );
        }
        return member;
    }

    abstract public void addNewToSet(GettableSet<? extends AbstractSetMember> gettableSet );
    abstract public void cleanUpAfterFindingGenuine(GettableSet<? extends AbstractSetMember> gettableSet );
}

... ব্যবহার মোটামুটি সুস্পষ্ট (আপনার ভিতরে SomeClass'র staticকারখানা পদ্ধতি):

SomeClass setMember = new SomeClass( param1, param2 ).addOrGetExisting( set );

0

হ্যাশ কোডের চুক্তিটি পরিষ্কার করে দেয় যে:

"যদি অবজেক্ট পদ্ধতি অনুসারে দুটি বস্তু সমান হয়, তবে দুটি বস্তুর প্রত্যেকটিতে হ্যাশকোড পদ্ধতিতে কল করার জন্য একই সংখ্যার ফলাফল হতে হবে" "

সুতরাং আপনার অনুমান:

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

ভুল এবং আপনি চুক্তি ভঙ্গ করছেন। যদি আমরা সেট ইন্টারফেসের "অন্তর্ভুক্ত" পদ্ধতিটি দেখি তবে আমাদের তা রয়েছে:

বুলিয়ান থাকে (অবজেক্ট ও);
যদি এই সেটটিতে নির্দিষ্ট উপাদান থাকে তবে সত্য ফিরে আসে। আরও আনুষ্ঠানিকভাবে, সত্যটি ফিরে আসে যদি এবং কেবলমাত্র এই সেটটিতে এমন কোনও উপাদান রয়েছে যে "ই" যেমন o == নাল? e == নাল: o.equals (e)

আপনি যা চান তা অর্জন করতে আপনি একটি মানচিত্র ব্যবহার করতে পারেন যেখানে আপনি কীটি সংজ্ঞায়িত করতে পারেন এবং কী উপাদান দিয়ে আপনার উপাদানটি সংরক্ষণ করতে পারেন যা কীভাবে বস্তুগুলি একে অপরের সমান বা সমান def


-2

দ্রুত সহায়তাকারী পদ্ধতি যা এই পরিস্থিতির সমাধান করতে পারে:

<T> T onlyItem(Collection<T> items) {
    if (items.size() != 1)
        throw new IllegalArgumentException("Collection must have single item; instead it has " + items.size());

    return items.iterator().next();
}

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

-2

নিম্নলিখিত একটি পদ্ধতির হতে পারে

   SharedPreferences se_get = getSharedPreferences("points",MODE_PRIVATE);
   Set<String> main = se_get.getStringSet("mydata",null);
   for(int jk = 0 ; jk < main.size();jk++)
   {
      Log.i("data",String.valueOf(main.toArray()[jk]));
   }

-2

একটি অ্যারে ব্যবহার করে দেখুন:

ObjectClass[] arrayName = SetOfObjects.toArray(new ObjectClass[setOfObjects.size()]);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.