জাভাতে সমান এবং হ্যাশকোডকে ওভাররাইড করার সময় কোন বিষয়গুলি বিবেচনা করা উচিত?


617

ওভাররাইড করার সময় কোন বিষয়গুলি / সমস্যাগুলি অবশ্যই বিবেচনা করা উচিত equalsএবং hashCode?

উত্তর:


1438

তত্ত্ব (ভাষা আইনজীবীদের এবং গাণিতিকভাবে ঝুঁকির জন্য):

equals()( Javadoc ) একজন সমানতা সম্পর্ক সংজ্ঞায়িত করতে হবে (এটা হতে হবে আত্মবাচক , প্রতিসম এবং সকর্মক )। তদ্ব্যতীত, এটি অবশ্যই সামঞ্জস্যপূর্ণ হতে হবে (যদি বস্তুগুলি সংশোধন না করা হয় তবে অবশ্যই এটির একই মানটি ফেরত যেতে হবে)। তদ্ব্যতীত, o.equals(null)সর্বদা মিথ্যা ফিরে আসতে হবে।

hashCode()( জাভাদোক ) অবশ্যই সামঞ্জস্যপূর্ণ হতে হবে (যদি পদটিকে শর্তে পরিবর্তিত না করা হয় তবে equals()এটি অবশ্যই একই মানটি ফেরত রাখতে হবে)।

সম্পর্ক দুটি পদ্ধতির মধ্যে হল:

যখনই a.equals(b), তখন a.hashCode()অবশ্যই একই হতে হবে b.hashCode()

প্রস্তুতিতে:

আপনি যদি একটিটিকে ওভাররাইড করে থাকেন তবে আপনার অন্যটিকে ওভাররাইড করা উচিত।

আপনি ক্ষেত্রগুলির একই সেট ব্যবহার করুন যা আপনি গণনা equals()করতে ব্যবহার করেন hashCode()

অ্যাপাচি কমন্স ল্যাং লাইব্রেরি থেকে ইকুয়ালস বিল্ডার এবং হ্যাশকোডবিল্ডার দুর্দান্ত সহায়ক ক্লাসগুলি ব্যবহার করুন । একটি উদাহরণ:

public class Person {
    private String name;
    private int age;
    // ...

    @Override
    public int hashCode() {
        return new HashCodeBuilder(17, 31). // two randomly chosen prime numbers
            // if deriving: appendSuper(super.hashCode()).
            append(name).
            append(age).
            toHashCode();
    }

    @Override
    public boolean equals(Object obj) {
       if (!(obj instanceof Person))
            return false;
        if (obj == this)
            return true;

        Person rhs = (Person) obj;
        return new EqualsBuilder().
            // if deriving: appendSuper(super.equals(obj)).
            append(name, rhs.name).
            append(age, rhs.age).
            isEquals();
    }
}

এছাড়াও মনে রাখবেন:

যখন ব্যবহার করে একটি হ্যাশ ভিত্তিক সংগ্রহ বা ম্যাপ যেমন HashSet , LinkedHashSet , HashMap , hashtable , অথবা WeakHashMap , নিশ্চিত করুন যে হ্যাশকোড () কী বস্তুর যে আপনার সংগ্রহে মধ্যে কখনোই করা যখন বস্তুর সংগ্রহে রয়েছে পরিবর্তন করুন। এটি নিশ্চিত করার বুলেটপ্রুফ উপায়টি হ'ল আপনার কীগুলি অপরিবর্তনীয় করে তোলা, এতে অন্যান্য সুবিধাও রয়েছে


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

312
আপনার জন্য দুটি পদ্ধতি উত্পন্ন করার জন্য আপনি Elpipse পেতে পারেন: উত্স> হ্যাশকোড () উত্পন্ন করুন এবং সমান ()।
রক স্ট্রিনিয়া

27
একই Netbeans সঙ্গে সত্য: developmentality.wordpress.com/2010/08/24/...
seinecle

6
@ ডারথিনিয়াস ইক্লিপস জেনারেটেড সমান গেটক্লাস () ব্যবহার করে যা কিছু ক্ষেত্রে সমস্যা দেখা দিতে পারে (কার্যকর জাভা আইটেম দেখুন 8)
অ্যান্ড্রয়েডগেকো

7
instanceofযদি প্রথম অপারেন্ডটি নাল হয় তবে মিথ্যা ফেরত দেওয়ার পরে প্রথম নাল চেকের প্রয়োজন নেই (কার্যকর জাভা আবার)।
ইজাবান

295

হাইবারনেটের মতো অবজেক্ট-রিলেশনশিপ ম্যাপার (ওআরএম) ব্যবহার করে অবিচ্ছিন্ন ক্লাসগুলির সাথে যদি আপনি আচরণ করছেন এমনটি বিবেচনা করার মতো কিছু বিষয় রয়েছে, যদি আপনি ভাবেন না যে এটি ইতিমধ্যে অযৌক্তিকভাবে জটিল ছিল!

অলস বোঝা বস্তুগুলি সাবক্লাস হয়

যদি আপনার অবজেক্টগুলি একটি ওআরএম ব্যবহার করে অবিচল থাকে, তবে অনেক ক্ষেত্রে ডেটা স্টোর থেকে খুব তাড়াতাড়ি বস্তু লোড করা এড়াতে আপনি গতিশীল প্রক্সিগুলির সাথে ডিল করবেন। এই প্রক্সিগুলি আপনার নিজের শ্রেণীর সাবক্লাস হিসাবে প্রয়োগ করা হয়েছে। এর অর্থ this.getClass() == o.getClass()ফিরে আসবে false। উদাহরণ স্বরূপ:

Person saved = new Person("John Doe");
Long key = dao.save(saved);
dao.flush();
Person retrieved = dao.retrieve(key);
saved.getClass().equals(retrieved.getClass()); // Will return false if Person is loaded lazy

আপনি যদি কোনও ওআরএম নিয়ে কাজ করছেন তবে ব্যবহার করা o instanceof Personহ'ল একমাত্র জিনিস যা সঠিকভাবে আচরণ করবে।

অলস বোঝা বস্তুর নালার ক্ষেত্র রয়েছে

ওআরএমগুলি সাধারণত অলস বোঝা বস্তুগুলির লোড করার জন্য জেটরগুলি ব্যবহার করে। এর অর্থ এই যে person.nameহতে হবে nullযদি person, অলস লোড হয় এমনকি যদি person.getName()বাহিনী লোড হচ্ছে এবং আয় "জন ডো"। আমার অভিজ্ঞতায়, এই ফসলগুলি প্রায়শই বেশি হয় hashCode()এবং equals()

আপনি যদি একটি ORM সাথে এসেছেন অধিনস্ত, সবসময় getters, এবং কখনও ক্ষেত্র রেফারেন্স ব্যবহার নিশ্চিত করতে hashCode()এবং equals()

কোনও বস্তু সংরক্ষণ করা তার অবস্থার পরিবর্তন করবে

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

একটি প্যাটার্ন যা আমি প্রায়শই ব্যবহার করি is

if (this.getId() == null) {
    return this == other;
}
else {
    return this.getId().equals(other.getId());
}

কিন্তু: আপনি অন্তর্ভুক্ত থাকতে পারে না getId()যে hashCode()। আপনি যদি করেন, যখন কোনও বস্তু স্থির থাকে, তখন তার hashCodeপরিবর্তন ঘটে। যদি বস্তুটি একটিতে থাকে তবে আপনি HashSetএটি আর "কখনই খুঁজে পাবেন না"।

আমার Personউদাহরণে, আমি সম্ভবত এর getName()জন্য hashCodeএবং getId()আরও getName()(কেবলমাত্র প্যারানাইয়ার জন্য) ব্যবহার করব equals()। যদি "সংঘর্ষ" হওয়ার কিছু ঝুঁকি থাকে hashCode()তবে তা ঠিক আছে, তবে কখনই ঠিক হবে না equals()

hashCode() থেকে বৈশিষ্ট্যের অ-পরিবর্তনশীল সাবসেট ব্যবহার করা উচিত equals()


2
@ জোহানেস ব্রডওয়াল: আমি বুঝতে পারছি না Saving an object will change it's state! hashCodeঅবশ্যই ফিরে আসবেন int, তাহলে আপনি কীভাবে ব্যবহার করবেন getName()? আপনি কি এর জন্য একটি উদাহরণ দিতে পারেনhashCode
জিমিবান্ডি

@ জিমিবান্ডি: getName একটি স্ট্রিং অবজেক্ট ফিরিয়ে দেবে যাতে একটি হ্যাশকোড রয়েছে যা ব্যবহার করা যেতে পারে
mateusz.fiolka

85

সম্পর্কে একটি ব্যাখ্যা obj.getClass() != getClass()

এই বিবৃতিটি equals()বন্ধুত্বপূর্ণভাবে উত্তরাধিকারী হওয়ার ফলাফল । জেএলএস (জাভা ভাষার স্পেসিফিকেশন) নির্দিষ্ট করে যে যদি A.equals(B) == trueতা হলে B.equals(A)আবারও ফিরে আসতে হবে true। যদি আপনি সেই বিবৃতিটি উত্তরাধিকার সূত্রে ক্লাস করে যেগুলি ওভাররাইড করে equals()(এবং এর আচরণ পরিবর্তন করে) এই স্পেসিফিকেশনটি ভেঙে দেয়।

বিবৃতি বাদ দিলে কী ঘটে যায় তার নিম্নলিখিত উদাহরণটি বিবেচনা করুন:

    class A {
      int field1;

      A(int field1) {
        this.field1 = field1;
      }

      public boolean equals(Object other) {
        return (other != null && other instanceof A && ((A) other).field1 == field1);
      }
    }

    class B extends A {
        int field2;

        B(int field1, int field2) {
            super(field1);
            this.field2 = field2;
        }

        public boolean equals(Object other) {
            return (other != null && other instanceof B && ((B)other).field2 == field2 && super.equals(other));
        }
    }    

এরকম new A(1).equals(new A(1))এছাড়াও, new B(1,1).equals(new B(1,1))সত্য খুঁজে দিতে, যেমন এটি করা উচিত স্থাপিত।

এটি দেখতে খুব সুন্দর দেখাচ্ছে, তবে দেখুন যদি আমরা উভয় শ্রেণি ব্যবহারের চেষ্টা করি তবে কী ঘটে:

A a = new A(1);
B b = new B(1,1);
a.equals(b) == true;
b.equals(a) == false;

অবশ্যই, এটি ভুল।

যদি আপনি প্রতিসামগ্রিক অবস্থা নিশ্চিত করতে চান। a = b if b = a এবং লিসকোভ প্রতিস্থাপনের নীতি super.equals(other)কেবল Bউদাহরণের ক্ষেত্রে নয়, উদাহরণস্বরূপ চেক করুন A:

if (other instanceof B )
   return (other != null && ((B)other).field2 == field2 && super.equals(other)); 
if (other instanceof A) return super.equals(other); 
   else return false;

যা আউটপুট দেবে:

a.equals(b) == true;
b.equals(a) == true;

যেখানে, যদি এটির aকোনও রেফারেন্স না হয় B, তবে এটি ক্লাসের একটি রেফারেন্স হতে পারে A(কারণ আপনি এটি প্রসারিত করেন), এক্ষেত্রে super.equals() আপনিও কল করেন ।


2
আপনি এইভাবে সমতুল্য প্রতিসাম্য তৈরি করতে পারেন (যদি সাবক্লাস অবজেক্টের সাথে একটি সুপারক্লাস অবজেক্টের তুলনা করা হয় তবে সর্বদা সাবক্লাসের সমতুল্য ব্যবহার করুন) যদি (obj.getClass ()! = This.getClass () && obj.getClass () .Isstance (এটি) ) রিটার্ন আপজেজ.একুয়ালস (এটি);
পাইথেনগি

5
@ পাইহেনতাগি - বাস্তবায়ন শ্রেণীর সমান পদ্ধতিতে ওভাররাইড না করা হলে আমি একটি স্ট্যাকওভারফ্লো পেয়ে যাব। মজা না.
রান বিরন

2
আপনি স্ট্যাকওভারফ্লো পাবেন না। যদি সমান পদ্ধতিটি ওভাররাইড না করা হয় তবে আপনি আবার একই কোডটি কল করবেন তবে পুনরাবৃত্তি করার শর্তটি সর্বদা মিথ্যা হবে!
জ্যাকব রায়হলে 4'13

@ পাইহেনতাগি: দুটি ভিন্ন ভিন্ন উত্পন্ন ক্লাস থাকলে তা কীভাবে আচরণ করবে? যদি কোনও সরবরাহকারীর ThingWithOptionSetAসমান হতে পারে Thingযে সমস্ত অতিরিক্ত বিকল্পের ডিফল্ট মান রয়েছে এবং একইভাবে একটি এর জন্য ThingWithOptionSetB, তবে উভয় অবজেক্টের সমস্ত বেস-ভিত্তিক বৈশিষ্ট্যগুলি তাদের ডিফল্টগুলির সাথে মিলে গেলে কেবল ThingWithOptionSetAএকটির সমান তুলনা করা সম্ভব হবে ThingWithOptionSetBতবে আমি দেখতে পাচ্ছি না যে আপনি এটির জন্য কীভাবে পরীক্ষা করছেন।
সুপারক্যাট

7
এটির সাথে সমস্যা এটি ট্রানজিটিভিটি ভেঙে দেয়। আপনি যোগ তাহলে B b2 = new B(1,99)তারপর, b.equals(a) == trueএবং a.equals(b2) == trueকিন্তু b.equals(b2) == false
নিকগ্রিম

46

উত্তরাধিকার-বান্ধব প্রয়োগের জন্য, তাল কোহেনের সমাধানটি দেখুন, আমি কীভাবে সমান () পদ্ধতিটি সঠিকভাবে প্রয়োগ করব?

সারসংক্ষেপ:

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

তার সমাধানটি হ'ল অন্য সংখ্যক অন্ধভাবেই কোয়েস্টস () উভয় উপায়ে কল করে সমান () প্রয়োগ করা। অন্ধভাবেইকুয়ালস () উপক্লাস দ্বারা ওভাররাইড করা হয়, সমান () উত্তরাধিকার সূত্রে প্রাপ্ত হয়, এবং কখনই ওভাররাইড হয় না।

উদাহরণ:

class Point {
    private int x;
    private int y;
    protected boolean blindlyEquals(Object o) {
        if (!(o instanceof Point))
            return false;
        Point p = (Point)o;
        return (p.x == this.x && p.y == this.y);
    }
    public boolean equals(Object o) {
        return (this.blindlyEquals(o) && o.blindlyEquals(this));
    }
}

class ColorPoint extends Point {
    private Color c;
    protected boolean blindlyEquals(Object o) {
        if (!(o instanceof ColorPoint))
            return false;
        ColorPoint cp = (ColorPoint)o;
        return (super.blindlyEquals(cp) && 
        cp.color == this.color);
    }
}

নোট করুন যে লিসকভ সাবস্টিটিউশন নীতিটি সন্তুষ্ট করতে হলে সমান () অবশ্যই উত্তরাধিকারের স্তরক্রম জুড়ে কাজ করতে হবে।


10
এখানে বর্ণিত CanEqual পদ্ধতিটি একবার দেখুন - একই নীতি উভয় সমাধানকে কাজ করে তোলে, তবে canEqual দিয়ে আপনি একই ক্ষেত্রের সাথে দু'বার তুলনা করেন না (উপরে, px == this.x উভয় দিক দিয়ে পরীক্ষা করা হবে): artima.com /lejava/articles/equality.html
ব্লেজারব্লেড

2
যাই হোক না কেন, আমি এটি একটি ভাল ধারণা বলে মনে করি না। এটি সমান চুক্তিটিকে অযৌক্তিকভাবে বিভ্রান্ত করে তোলে - যে কেউ দুটি পয়েন্ট প্যারামিটার, ক এবং খ গ্রহণ করে, তার সম্ভাবনা সম্পর্কে সচেতন থাকতে হবে যে a.getX () == বি.জেএক্সএক্স () এবং a.getY () == b.getY () সত্য হতে পারে তবে aqueals (খ) এবং b.equals (a) উভয়ই মিথ্যা (যদি কেবল একটি রঙিন পয়েন্ট থাকে)।
কেভিন

মূলত, এটি এর মতো if (this.getClass() != o.getClass()) return falseতবে নমনীয় যে এটি কেবলমাত্র মিথ্যা ফেরত দেয় যদি উত্পন্ন শ্রেণি (এস) সমান পরিবর্তন করতে বিরক্ত করে। এটা কি সঠিক?
আলেকসান্দ্র ডাবিনস্কি

31

এখনও অবাক হয়ে যায় যে কেউ এর জন্য পেয়ারা গ্রন্থাগারের সুপারিশ করেনি।

 //Sample taken from a current working project of mine just to illustrate the idea

    @Override
    public int hashCode(){
        return Objects.hashCode(this.getDate(), this.datePattern);
    }

    @Override
    public boolean equals(Object obj){
        if ( ! obj instanceof DateAndPattern ) {
            return false;
        }
        return Objects.equal(((DateAndPattern)obj).getDate(), this.getDate())
                && Objects.equal(((DateAndPattern)obj).getDate(), this.getDatePattern());
    }

23
java.util.Objects.hash () এবং java.util.Objects.equals () জাভা of এর অংশ (২০১১ সালে প্রকাশিত) সুতরাং এর জন্য আপনার পেয়ারা লাগবে না।
Herman

1
অবশ্যই, তবে আপনার এড়ানো উচিত যেহেতু ওরাকল জাভা 6 এর জন্য পাবলিক আপডেট সরবরাহ করছে না (ফেব্রুয়ারী 2013 এর পর থেকে এটিই হয়েছে)।
হারমান

6
তোমার thisমধ্যে this.getDate()উপায়ে কিছুই (গোলমাল ছাড়া)
স্টিভ Kuo থেকে

1
আপনার "instanceof নয়" অভিব্যক্তি একটি অতিরিক্ত বন্ধনী দরকার: if (!(otherObject instanceof DateAndPattern)) {। হেনান এবং স্টিভ কুও (যদিও এটি ব্যক্তিগত পছন্দের বিষয়) এর সাথে সম্মত হন তবে তা তবে +1 করুন।
আমোস এম কার্পেন্টার

26

সুপার ক্লাসে জাভা.লং.অবজেক্ট হিসাবে দুটি পদ্ধতি রয়েছে। আমাদের সেগুলি কাস্টম অবজেক্টে ওভাররাইড করা দরকার।

public boolean equals(Object obj)
public int hashCode()

সমান অবজেক্টগুলিকে অবশ্যই একই হ্যাশ কোড তৈরি করা উচিত যতক্ষণ না তারা সমান হয় তবে অসম বস্তুগুলিতে স্বতন্ত্র হ্যাশ কোড তৈরি করার প্রয়োজন হয় না।

public class Test
{
    private int num;
    private String data;
    public boolean equals(Object obj)
    {
        if(this == obj)
            return true;
        if((obj == null) || (obj.getClass() != this.getClass()))
            return false;
        // object must be Test at this point
        Test test = (Test)obj;
        return num == test.num &&
        (data == test.data || (data != null && data.equals(test.data)));
    }

    public int hashCode()
    {
        int hash = 7;
        hash = 31 * hash + num;
        hash = 31 * hash + (null == data ? 0 : data.hashCode());
        return hash;
    }

    // other methods
}

আপনি যদি আরও কিছু পেতে চান তবে দয়া করে এই লিঙ্কটি http://www.javaranch.com/j Journal/2002/10/ equalhash.html হিসাবে চেক করুন

এটি অন্য একটি উদাহরণ, http://java67.blogspot.com/2013/04/example-of-overriding-equals-hashcode-compareTo-java-method.html

আনন্দ কর! @। @


দুঃখিত তবে আমি হ্যাশকোড পদ্ধতি সম্পর্কে এই বিবৃতিটি বুঝতে পারি না: এটি সমান () এর চেয়ে বেশি ভেরিয়েবল ব্যবহার করলে এটি আইনী নয়। তবে আমি যদি আরও ভেরিয়েবলগুলির সাথে কোড করি তবে আমার কোডটি সংকলন করে। কেন এটি আইনী নয়?
অ্যাড্রির 83

19

সদস্যের সাম্যতা যাচাই করার আগে শ্রেণি সমতার জন্য আপনার চেক করার কয়েকটি উপায় রয়েছে এবং আমি মনে করি উভয়ই সঠিক পরিস্থিতিতে কার্যকর।

  1. instanceofঅপারেটরটি ব্যবহার করুন ।
  2. ব্যবহার this.getClass().equals(that.getClass())

আমি finalসমান রূপায়ণে # 1 ব্যবহার করি বা এমন একটি ইন্টারফেস প্রয়োগ করি যা সমান জন্য একটি অ্যালগরিদম নির্ধারণ করে (যেমন java.utilসংগ্রহের ইন্টারফেসগুলি — যেমন (obj instanceof Set)আপনি প্রয়োগ করছেন এমন ইন্টারফেসের সাথে যাচাই করার সঠিক উপায় )। সমতুল্য যখন ওভাররাইড করা যায় তখন এটি সাধারণত একটি খারাপ পছন্দ কারণ এটি প্রতিসাম্য সম্পত্তিকে ভেঙে দেয়।

# 2 বিকল্পটি সমান ওভারাইডিং বা প্রতিসাম্যতা ভঙ্গ না করে ক্লাসটিকে নিরাপদে প্রসারিত করতে দেয়।

আপনার ক্লাসটি যদি হয় Comparableতবে equalsএবং compareToপদ্ধতিগুলিও সামঞ্জস্যপূর্ণ হওয়া উচিত। এখানে একটি Comparableশ্রেণিতে সমান পদ্ধতির জন্য একটি টেম্পলেট রয়েছে :

final class MyClass implements Comparable<MyClass>
{

  

  @Override
  public boolean equals(Object obj)
  {
    /* If compareTo and equals aren't final, we should check with getClass instead. */
    if (!(obj instanceof MyClass)) 
      return false;
    return compareTo((MyClass) obj) == 0;
  }

}

1
এই জন্য +1। গেটক্লাস () বা উদাহরণস্বরূপ উভয়ই একটি প্যানাসিয়া নয় এবং এটি উভয়ের কাছে কীভাবে যেতে হবে তার এটি একটি ভাল ব্যাখ্যা। সমান () ব্যবহার করার পরিবর্তে এটি.বিটক্লাস () == that.getClass () না করার কোনও কারণ নেই বলে মনে করবেন না।
পল ক্যান্ট্রেল

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

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

মাইক্লাস এ = নতুন মাইক্লাস (123); মাইক্র্লাস বি = নতুন মাইক্লাস (123) {// কিছু পদ্ধতি ওভাররাইড করুন}; // a.equals (খ) মিথ্যা যখন this.getClass () ব্যবহার করছে সমকক্ষ স্থীর (that.getClass ())।
steinybot

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

16

সমান জন্য, দেখব সমান অফ সিক্রেটস দ্বারা Angelika ল্যাঙ্গার । আমি এটা খুব ভালবাসি. তিনি জাভা জেনেরিক্স সম্পর্কে দুর্দান্ত জিজ্ঞাসিত প্রশ্ন । তার অন্যান্য নিবন্ধগুলি এখানে দেখুন ("কোর জাভাতে" স্ক্রোল করুন), যেখানে তিনি পার্ট -২ এবং "মিশ্র প্রকারের তুলনা" নিয়েও চলেছেন। তাদের পড়তে মজা করুন!


11

সমান () পদ্ধতি দুটি বস্তুর সাম্য নির্ধারণ করতে ব্যবহৃত হয়।

10 এর int মান সর্বদা 10 এর সমান হয় তবে এই সমান () পদ্ধতিটি দুটি বস্তুর সমতা সম্পর্কে। যখন আমরা বস্তু বলি, এর বৈশিষ্ট্য থাকবে। সমতা সম্পর্কে সিদ্ধান্ত নিতে সেই বৈশিষ্ট্যগুলি বিবেচনা করা হয়। সমতা নির্ধারণের জন্য সমস্ত সম্পত্তি বিবেচনায় নিতে হবে এবং শ্রেণি সংজ্ঞা এবং প্রসঙ্গে শ্রদ্ধার সাথে এটি সিদ্ধান্ত নেওয়া যেতে পারে তা প্রয়োজনীয় নয়। তারপরে সমান () পদ্ধতিটি ওভাররাইড করা যায়।

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

প্রদত্ত ডিফল্ট বাস্তবায়ন হ্যাজকোড () পদ্ধতি অবজেক্ট শ্রেণিতে অবজেক্টের অভ্যন্তরীণ ঠিকানা ব্যবহার করে এবং এটি পূর্ণসংখ্যায় রূপান্তরিত করে এবং ফেরত দেয়।

public class Tiger {
  private String color;
  private String stripePattern;
  private int height;

  @Override
  public boolean equals(Object object) {
    boolean result = false;
    if (object == null || object.getClass() != getClass()) {
      result = false;
    } else {
      Tiger tiger = (Tiger) object;
      if (this.color == tiger.getColor()
          && this.stripePattern == tiger.getStripePattern()) {
        result = true;
      }
    }
    return result;
  }

  // just omitted null checks
  @Override
  public int hashCode() {
    int hash = 3;
    hash = 7 * hash + this.color.hashCode();
    hash = 7 * hash + this.stripePattern.hashCode();
    return hash;
  }

  public static void main(String args[]) {
    Tiger bengalTiger1 = new Tiger("Yellow", "Dense", 3);
    Tiger bengalTiger2 = new Tiger("Yellow", "Dense", 2);
    Tiger siberianTiger = new Tiger("White", "Sparse", 4);
    System.out.println("bengalTiger1 and bengalTiger2: "
        + bengalTiger1.equals(bengalTiger2));
    System.out.println("bengalTiger1 and siberianTiger: "
        + bengalTiger1.equals(siberianTiger));

    System.out.println("bengalTiger1 hashCode: " + bengalTiger1.hashCode());
    System.out.println("bengalTiger2 hashCode: " + bengalTiger2.hashCode());
    System.out.println("siberianTiger hashCode: "
        + siberianTiger.hashCode());
  }

  public String getColor() {
    return color;
  }

  public String getStripePattern() {
    return stripePattern;
  }

  public Tiger(String color, String stripePattern, int height) {
    this.color = color;
    this.stripePattern = stripePattern;
    this.height = height;

  }
}

কোড আউটপুট উদাহরণ:

bengalTiger1 and bengalTiger2: true 
bengalTiger1 and siberianTiger: false 
bengalTiger1 hashCode: 1398212510 
bengalTiger2 hashCode: 1398212510 
siberianTiger hashCode: 1227465966

7

যৌক্তিকভাবে আমাদের রয়েছে:

a.getClass().equals(b.getClass()) && a.equals(b)a.hashCode() == b.hashCode()

কিন্তু না ভাইস বিপরীতভাবে!


6

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

আপনি যদি আপনার হ্যাশকোডের সম্পর্কের উভয় প্রান্তকে অন্তর্ভুক্ত করেন বা পরীক্ষার সমান হয় তবে এটি পুনরাবৃত্ত লুপে প্রবেশ করা সম্ভব যা স্ট্যাকওভারফ্লো এক্সপেশনে শেষ হয়।
সহজ সমাধানটি পদ্ধতিগুলিতে getChildren সংগ্রহকে অন্তর্ভুক্ত না করা।


5
আমি মনে করি যে এখানে অন্তর্নিহিত তত্ত্বটি কোনও বস্তুর গুণাবলী , সমষ্টি এবং এসোসিয়েটিনোগুলির মধ্যে পার্থক্য করা । Asssociations অংশগ্রহণের করা উচিত নয় equals()। যদি কোনও পাগল বিজ্ঞানী আমার একটি সদৃশ তৈরি করে তবে আমরা সমান হতে পারি। তবে আমাদের একই পিতা থাকতেন না।
রায়েদওয়াল্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.