JavaRush /مدونة جافا /Random-AR /العمل باستخدام أساليب hashCode() وequals() في Java
Lenchik854
مستوى
Chernihiv

العمل باستخدام أساليب hashCode() وequals() في Java

نشرت في المجموعة
في هذا المنشور سأوضح فهمي للطرق hashCode()و equals(). أريد أن أتحدث عن تنفيذها الافتراضي، وكذلك كيفية تجاوزها بشكل صحيح. سأكتب أيضًا عن تنفيذ هذه الأساليب باستخدام الفئات المساعدة لحزمة Apache Common. العمل باستخدام أساليب hashCode() وequals() في Java - 1محتويات هذه التدوينة:
  1. باستخدام hashCode()و equals().
  2. تجاوز السلوك الافتراضي.
  3. تجاوز hashCode()واستخدام equals()Apache Commons Lang.
  4. شيء مهم أن نتذكره.
  5. اهتمام خاص عند استخدام ORM.
hashCode()تم تعريف الأساليب والطرق equals()في الفصل Object، وهو الفصل الأصلي لكائنات Java. لذلك، ترث كافة كائنات Java التنفيذ الافتراضي من هذه الطرق.

باستخدام hashCode() و يساوي()

يتم استخدام هذه الطريقة hashCode()للحصول على رقم صحيح فريد لكائن معين. عندما يلزم تخزين كائن ما كبنية بيانات في جدول التجزئة (يُسمى أيضًا الدلو)، يتم استخدام هذا الرقم لتحديد موقعه في هذا الجدول. بشكل افتراضي، تقوم الطريقة hashCode()الخاصة بالكائن بإرجاع رقم موقع الذاكرة حيث تم تخزين الكائن. تُستخدم الطريقة equals()، كما يوحي اسمها، للتحقق ببساطة من تساوي كائنين. يتحقق التنفيذ الافتراضي لهذه الطريقة ببساطة من مراجع كائنين لمعرفة ما إذا كانا متساويين.

تجاوز السلوك الافتراضي

كل شيء يعمل بشكل جيد طالما أنك لا تتجاوز أيًا من هذه الأساليب في فصولك الدراسية. لكن في بعض الأحيان تحتاج التطبيقات إلى تغيير السلوك الافتراضي لبعض الكائنات. لنأخذ مثالاً حيث لديك ملف Employee. دعونا نكتب الحد الأدنى من البنية الممكنة لمثل هذه الفئة.
public class Employee
{
    private Integer id;
    private String firstname;
    private String lastName;
    private String department;

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getFirstname() {
        return firstname;
    }
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getDepartment() {
        return department;
    }
    public void setDepartment(String department) {
        this.department = department;
    }
}
يحتوي الفصل الموضح أعلاه Employeeعلى بعض السمات الأساسية وطرق الوصول. الآن دعونا نلقي نظرة على موقف بسيط حيث نحتاج إلى مقارنة كائنين من الفئة Employee.
public class EqualsTest {
    public static void main(String[] args) {
        Employee e1 = new Employee();
        Employee e2 = new Employee();

        e1.setId(100);
        e2.setId(100);
        //Печатает false в консоли
        System.out.println(e1.equals(e2));
    }
}
لا يتطلب الأمر من العراف أن يخمن أن الطريقة المكتوبة أعلاه ستعيد "خطأ". لكن هل هذا صحيح بالفعل، نظرًا لأن هذين الجسمين متماثلان؟ في التطبيق في الوقت الحقيقي، يجب أن تعود الطريقة صحيحة. لتحقيق السلوك الصحيح، نحتاج إلى تجاوز الطريقة equals()، كما هو موضح أدناه:
public boolean equals(Object o) {
        if(o == null)
        {
            return false;
        }
        if (o == this)
        {
           return true;
        }
        if (getClass() != o.getClass())
        {
            return false;
        }
        Employee e = (Employee) o;
        return (this.getId() == e.getId());
}
أضف هذه الطريقة إلى صفك Employeeوسيعود فحص التكافؤ إلى القيمة "صحيح". ومع ذلك، هل فعلنا كل شيء؟ ليس بعد. دعونا نختبر فصلنا المعدل بطريقة أخرى.
import java.util.HashSet;
import java.util.Set;

public class EqualsTest
{
    public static void main(String[] args)
    {
        Employee e1 = new Employee();
        Employee e2 = new Employee();

        e1.setId(100);
        e2.setId(100);

        //Печатает 'true'
        System.out.println(e1.equals(e2));

        Set employees = new HashSet();
        employees.add(e1);
        employees.add(e2);
        //Печатает два an object
        System.out.println(employees);
    }
}
يقوم الأمر System.out.println(employee)بطباعة كائنين. إذا كان كلا الكائنين متكافئين، وتم Setاحتواء كائنات فريدة فقط، HashSetفيجب أن يكون هناك مثيل واحد فقط بالداخل، أي. يشير كلا الكائنين إلى نفس مثيلات الفئة Employee. ماذا فاتنا؟ لقد فاتنا الطريقة الثانية المهمة hashCode(). كما تقول وثائق جافا، إذا قمت بتجاوز الطريقة equals()، فستتم مطالبتك بتجاوز الطريقة hashCode(). لذلك دعونا نضيف طريقة أخرى لفصلنا Employee.
@Override
 public int hashCode()
 {
    final int PRIME = 31;
    int result = 1;
    result = PRIME * result + getId();
    return result;
 }
لقد أضفنا هذه الطريقة مرة واحدة إلى فصلنا، وسيتم طباعة كائن واحد فقط، وبالتالي فإن التحقق من تكافؤ e1 و e2 أثبت صحته.

تجاوز hashCode()واستخدام equals()Apache Commons Lang

يوفر Apache Commons فئتين مساعدتين رائعتين لطرق الاتصال hashCode()و equals(). أدناه نرى الاستخدام:
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
public class Employee
{
 private Integer id;
 private String firstname;
 private String lastName;
 private String department;
public Integer getId() {
    return id;
 }
 public void setId(Integer id) {
    this.id = id;
 }
 public String getFirstname() {
    return firstname;
 }
 public void setFirstname(String firstname) {
    this.firstname = firstname;
 }
 public String getLastName() {
    return lastName;
 }
 public void setLastName(String lastName) {
    this.lastName = lastName;
 }
 public String getDepartment() {
    return department;
 }
 public void setDepartment(String department) {
    this.department = department;
 }
@Override
 public int hashCode()
 {
    final int PRIME = 31;
    return new HashCodeBuilder(getId()%2==0?getId()+1:getId(), PRIME).
           toHashCode();
 }
@Override
 public boolean equals(Object o) {
    if (o == null)
       return false;
    if (o == this)
       return true;
    if (o.getClass() != getClass())
       return false;
    Employee e = (Employee) o;
       return new EqualsBuilder().
              append(getId(), e.getId()).
              isEquals();
    }
 }
من ناحية أخرى، إذا كنت تستخدم أحد برامج تحرير التعليمات البرمجية، فمن المفترض أيضًا أن يكونوا قادرين على استدعاء بعض الهياكل الرائعة لك. على سبيل المثال، إذا نقرت بزر الماوس الأيمن في Eclipse IDE على الفئة >> source > Geneuring hashCode() وequals()... فسوف يؤدي ذلك إلى إنشاء تطبيق رائع جدًا لك. العمل باستخدام أساليب hashCode() وequals() في Java - 2شيء مهم أن نتذكره.
  1. استخدم دائمًا نفس سمات الكائن للاتصال بكل من و hashCode()و equals(). فقط في حالتنا استخدمنا employee id.
  2. يجب أن تكون الطريقة equals()ثابتة (إذا لم يتغير الكائن، فيجب أن تُرجع الطريقة نفس القيمة).
  3. كلما a.equals(b)، a.hashCode()يجب أن يكون هو نفسه b.hashCode().
  4. إذا قمت بتجاوز إحدى الطرق، فيجب عليك تجاوز الطريقة الثانية.

اهتمام خاص عند استخدام ORM

إذا كنت تتعامل مع ORM (ru.wikipedia.org/wiki/ORM)، فاستخدم الحروف دائمًا ولا تستخدم مراجع الحقول مطلقًا hashCode(). equals()هذا لأنه في ORM، يتم تحميل الحقول من وقت لآخر باستخدام التحميل البطيء ولا يمكن الوصول إليها حتى يتم استدعاء الحروف الخاصة بها. على سبيل المثال، في فصلنا Employeeنستخدم e1.id == e2.id. من الممكن تمامًا أن iيتم تحميل الحقول d باستخدام التحميل البطيء. قد يكون أحد الحقول 0 أو فارغًا وسنحصل على سلوك غير صحيح. ولكن، إذا تم استخدامه e1.getId() == e2.getId()، يمكننا التأكد حتى لو تم تحميل الحقول باستخدام التحميل البطيء؛ سيؤدي استدعاء getter إلى ملء الحقل أولاً. هذا كل ما أعرفه عن الأساليب hashCode()والأساليب equals(). نأمل أن يساعد هذا شخص ما في مكان ما. حظا موفقا في دراستك!! ملاحظة: هذه هي محاولتي الأولى للترجمة. حاولت أن أنقل كل شيء في أقرب وقت ممكن مما أراد المؤلف قوله. إذا كان لديك أي تعليقات، يرجى الكتابة في التعليقات. لا تحكم بدقة :-))) المقال الأصلي
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION