equals
มีhashCode
ความเกี่ยวข้องกันอย่างใกล้ชิด และขอแนะนำให้แทนที่ทั้งสองวิธีในคลาสของตนอย่างสม่ำเสมอ จำนวนที่น้อยกว่าเล็กน้อยรู้ว่าเหตุใดจึงเป็นเช่นนั้น และผลที่ตามมาอันน่าเศร้าที่อาจเกิดขึ้นหากกฎนี้ละเมิด ฉันเสนอให้พิจารณาแนวคิดของวิธีการเหล่านี้ ทำซ้ำวัตถุประสงค์และทำความเข้าใจว่าทำไมจึงเชื่อมโยงกัน ฉันเขียนบทความนี้เช่นเดียวกับบทความก่อนหน้าเกี่ยวกับการโหลดคลาสเพื่อตัวฉันเองเพื่อที่จะเปิดเผยรายละเอียดทั้งหมดของปัญหาในที่สุดและจะไม่กลับไปยังแหล่งข้อมูลบุคคลที่สามอีกต่อไป ดังนั้นฉันยินดีที่จะวิจารณ์อย่างสร้างสรรค์เพราะหากมีช่องว่างที่ไหนสักแห่งก็ควรจะกำจัดออกไป อนิจจาบทความกลายเป็นเรื่องที่ค่อนข้างยาว
เท่ากับแทนที่กฎ
วิธีการequals()
ที่จำเป็นใน Java เพื่อยืนยันหรือปฏิเสธความจริงที่ว่าสองวัตถุที่มีต้นกำเนิดเดียวกันมีความเท่าเทียมกันทางตรรกะ นั่นคือ เมื่อเปรียบเทียบวัตถุสองชิ้น โปรแกรมเมอร์จำเป็นต้องเข้าใจว่าสาขาที่มีนัยสำคัญ นั้นเทียบเท่ากันหรือ ไม่ ไม่จำเป็นว่าทุกฟิลด์จะต้องเหมือนกัน เนื่องจากวิธีการนี้แสดงequals()
ถึงความเท่าเทียมกันทางตรรกะ แต่บางครั้งก็ไม่จำเป็นต้องใช้วิธีนี้เป็นพิเศษ อย่างที่พวกเขาพูดกันว่าวิธีที่ง่ายที่สุดในการหลีกเลี่ยงปัญหาโดยใช้กลไกเฉพาะคือการไม่ใช้มัน ควรสังเกตว่าเมื่อคุณผิดสัญญาequals
คุณจะสูญเสียการควบคุมในการทำความเข้าใจว่าวัตถุและโครงสร้างอื่นจะโต้ตอบกับวัตถุของคุณอย่างไร และการค้นหาสาเหตุของข้อผิดพลาดในภายหลังจะเป็นเรื่องยากมาก
เมื่อไม่แทนที่วิธีนี้
- เมื่อแต่ละอินสแตนซ์ของคลาสไม่ซ้ำกัน ในระดับที่มากขึ้น สิ่งนี้ใช้กับคลาสที่มีพฤติกรรมเฉพาะ แทนที่จะได้รับการออกแบบให้ทำงานกับข้อมูล เช่นเช่นในชั้น
- เมื่อในความเป็นจริงแล้ว คลาสไม่จำเป็นต้องกำหนดความเท่าเทียมกันของอินสแตนซ์ ตัวอย่างเช่น สำหรับคลาสหนึ่งๆ
- เมื่อคลาสที่คุณกำลังขยายมีการนำเมธอดไปใช้แล้ว
equals
และพฤติกรรมของการใช้งานนี้เหมาะสมกับคุณ ตัวอย่างเช่น สำหรับคลาส, - และสุดท้าย ไม่จำเป็นต้องแทนที่
equals
เมื่อขอบเขตของคลาสของคุณเป็นprivate
หรือpackage-private
และคุณแน่ใจว่าเมธอดนี้จะไม่มีวันถูกเรียกใช้
Thread
เรียน สำหรับพวกเขาequals
การใช้วิธีการที่คลาสมีให้นั้นObject
ก็เกินพอแล้ว อีกตัวอย่างหนึ่งคือคลาสแจงนับ ( Enum
)
java.util.Random
ไม่จำเป็นต้องเปรียบเทียบอินสแตนซ์ของคลาสด้วยกันเลย โดยพิจารณาว่าอินสแตนซ์เหล่านั้นสามารถส่งคืนตัวเลขสุ่มลำดับเดียวกันได้หรือไม่ เพียงเพราะธรรมชาติของชั้นเรียนนี้ไม่ได้หมายความถึงพฤติกรรมดังกล่าวด้วยซ้ำ
Set
การใช้งานจะอยู่ในและตามลำดับ List
Map
equals
AbstractSet
AbstractList
AbstractMap
เท่ากับสัญญา
เมื่อแทนที่เมธอดequals
นักพัฒนาจะต้องปฏิบัติตามกฎพื้นฐานที่กำหนดไว้ในข้อกำหนดภาษา Java
- สะท้อนแสง สำหรับค่าที่กำหนดใดๆ
- สมมาตร สำหรับค่าที่กำหนดใด ๆและ
- การขนส่ง สำหรับค่าที่กำหนดใดๆและ
- ความสม่ำเสมอ สำหรับค่าที่กำหนดใดๆ
- การเปรียบเทียบเป็นโมฆะ สำหรับมูลค่าที่กำหนดใด ๆ
x
นิพจน์x.equals(x)
จะต้องส่งtrue
คืน
ให้ - ความหมายเช่นนั้น
x != null
x
ควรส่งคืนเฉพาะในกรณีที่ส่ง คืนy
x.equals(y)
true
y.equals(x)
true
x
หากy
ส่งคืนz
และส่งคืนจะต้องส่งคืนค่านั้นx.equals(y)
true
y.equals(z)
true
x.equals(z)
true
x
และy
การเรียกซ้ำx.equals(y)
จะส่งกลับค่าของการเรียกครั้งก่อนเป็นเมธอดนี้ โดยมีเงื่อนไขว่าฟิลด์ที่ใช้ในการเปรียบเทียบทั้งสองอ็อบเจ็กต์ไม่เปลี่ยนแปลงระหว่างการโทร
x
การโทรx.equals(null)
จะต้องส่งfalse
คืน
เท่ากับผิดสัญญา
คลาสจำนวนมาก เช่น คลาสจาก Java Collections Framework ขึ้นอยู่กับการใช้งานเมธอดequals()
ดังนั้นคุณจึงไม่ควรละเลยเพราะ การละเมิดสัญญาของวิธีการนี้อาจนำไปสู่การดำเนินการที่ไม่มีเหตุผลของแอปพลิเคชันและในกรณีนี้การค้นหาสาเหตุจะค่อนข้างยาก ตามหลักการสะท้อนกลับวัตถุทุกชิ้นจะต้องมีค่าเท่ากันกับตัวมันเอง หากหลักการนี้ถูกละเมิด เมื่อเราเพิ่มวัตถุเข้าไปในคอลเลกชันแล้วค้นหาโดยใช้วิธีการcontains()
เราจะไม่สามารถค้นหาวัตถุที่เราเพิ่งเพิ่มเข้าไปในคอลเลกชันได้ เงื่อนไขสมมาตรระบุว่าวัตถุสองชิ้นใดๆ จะต้องเท่ากันโดยไม่คำนึงถึงลำดับการเปรียบเทียบ equals
ตัวอย่างเช่น หากคุณมีคลาสที่มีฟิลด์ประเภทสตริงเพียงฟิลด์เดียว การเปรียบเทียบ ฟิลด์นี้กับสตริงในเมธอดจะไม่ถูกต้อง เพราะ ในกรณีที่มีการเปรียบเทียบแบบย้อนกลับ เมธอดจะส่งกลับค่าfalse
เสมอ
// Нарушение симметричности
public class SomeStringify {
private String s;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o instanceof SomeStringify) {
return s.equals(((SomeStringify) o).s);
}
// нарушение симметричности, классы разного происхождения
if (o instanceof String) {
return s.equals(o);
}
return false;
}
}
//Правильное определение метода equals
@Override
public boolean equals(Object o) {
if (this == o) return true;
return o instanceof SomeStringify &&
((SomeStringify) o).s.equals(s);
}
จากเงื่อนไขของการเปลี่ยนแปลงสภาพจะเป็นไปตามว่าหากวัตถุสองในสามชิ้นมีค่าเท่ากัน ในกรณีนี้ทั้งสามจะต้องเท่ากัน หลักการนี้สามารถถูกละเมิดได้ง่ายเมื่อจำเป็นต้องขยายคลาสฐานบางคลาสโดยการเพิ่มองค์ประกอบที่มีความหมาย ลงไป ตัวอย่างเช่น ในชั้นเรียนPoint
ที่มีพิกัดx
และy
คุณต้องเพิ่มสีของจุดโดยการขยาย ในการดำเนินการ นี้คุณจะต้องประกาศคลาสColorPoint
ที่มีฟิลด์ที่เกี่ยวข้อง color
ดังนั้น หากในคลาสขยายเราเรียกเมธอดequals
parent และในคลาสพาเรนต์เราถือว่ามีเพียงพิกัดx
และ ถูกเปรียบเทียบ y
ดังนั้นจุดสองจุดที่มีสีต่างกันแต่มีพิกัดเดียวกันจะถือว่าเท่ากัน ซึ่งไม่ถูกต้อง ในกรณีนี้ จำเป็นต้องสอนคลาสที่ได้รับให้แยกแยะสีต่างๆ เมื่อต้องการทำเช่นนี้ คุณสามารถใช้สองวิธี แต่ใครจะฝ่าฝืนกฎของสมมาตรและประการที่สองคือการ เปลี่ยนแปลง
// Первый способ, нарушая симметричность
// Метод переопределен в классе ColorPoint
@Override
public boolean equals(Object o) {
if (!(o instanceof ColorPoint)) return false;
return super.equals(o) && ((ColorPoint) o).color == color;
}
ในกรณีนี้ การเรียกpoint.equals(colorPoint)
จะส่งคืนค่าtrue
และการเปรียบเทียบcolorPoint.equals(point)
จะส่งคืนfalse
เนื่องจาก คาดหวังวัตถุของคลาส "มัน" กฎแห่งความสมมาตรจึงถูกละเมิด วิธีที่สองเกี่ยวข้องกับการทำการตรวจสอบแบบ "ตาบอด" ในกรณีที่ไม่มีข้อมูลเกี่ยวกับสีของจุด เช่น เรามีPoint
คลาส ColorPoint
หรือตรวจสอบสีหากมี ข้อมูล เกี่ยวกับสีนั้น นั่นคือ เปรียบเทียบวัตถุของคลาส
// Метод переопределен в классе ColorPoint
@Override
public boolean equals(Object o) {
if (!(o instanceof Point)) return false;
// Слепая проверка
if (!(o instanceof ColorPoint))
return super.equals(o);
// Полная проверка, включая цвет точки
return super.equals(o) && ((ColorPoint) o).color == color;
}
หลักการของการขนส่งถูกละเมิดที่นี่ดังนี้ สมมติว่ามีคำจำกัดความของวัตถุต่อไปนี้:
ColorPoint p1 = new ColorPoint(1, 2, Color.RED);
Point p2 = new Point(1, 2);
ColorPoint p3 = new ColorPoint(1, 2, Color.BLUE);
ดังนั้นแม้ว่าจะมีความเท่าเทียมกันและp1.equals(p2)
พอใจp2.equals(p3)
แต่p1.equals(p3)
ก็จะส่งกลับค่า false
ในขณะเดียวกันวิธีที่สองในความคิดของฉันดูน่าดึงดูดน้อยกว่าเพราะ ในบางกรณี อัลกอริธึมอาจมองไม่เห็นและทำการเปรียบเทียบได้ไม่เต็มที่ และคุณอาจไม่ทราบเรื่องนี้ บทกวีเล็กน้อย โดยทั่วไปแล้ว ตามที่ฉันเข้าใจ ไม่มีวิธีแก้ปัญหาที่เป็นรูปธรรมสำหรับปัญหานี้ มีความคิดเห็นจากผู้เขียนที่เชื่อถือได้คนหนึ่งชื่อ Kay Horstmann ที่คุณสามารถแทนที่การใช้ตัวดำเนินการinstanceof
ด้วยการเรียกเมธอดgetClass()
ที่ส่งคืนคลาสของอ็อบเจ็กต์ และก่อนที่คุณจะเริ่มเปรียบเทียบอ็อบเจ็กต์ด้วยตนเอง ตรวจสอบให้แน่ใจว่าอ็อบเจ็กต์นั้นเป็นประเภทเดียวกัน และอย่าไปใส่ใจกับข้อเท็จจริงของต้นกำเนิดร่วมกัน ดังนั้นกฎของสมมาตรและการเปลี่ยนผ่านจะเป็นที่พอใจ แต่ในเวลาเดียวกัน Joshua Bloch นักเขียนอีกคนหนึ่งยืนอยู่อีกด้านหนึ่งของสิ่งกีดขวางซึ่งเชื่อว่าแนวทางนี้ละเมิดหลักการทดแทนของ Barbara Liskov หลักการนี้ระบุว่า“การเรียกโค้ดต้องปฏิบัติต่อคลาสฐานในลักษณะเดียวกับคลาสย่อยโดยไม่รู้ตัว ” และในแนวทางแก้ไขที่เสนอโดย Horstmann หลักการนี้ถูกละเมิดอย่างชัดเจน เนื่องจากขึ้นอยู่กับการนำไปปฏิบัติ สรุปชัดเจนว่าเรื่องนี้มืดมน ควรสังเกตว่า Horstmann ชี้แจงกฎสำหรับการใช้วิธีการของเขาและเขียนเป็นภาษาอังกฤษธรรมดาว่าคุณต้องตัดสินใจเกี่ยวกับกลยุทธ์เมื่อออกแบบคลาสและหากการทดสอบความเท่าเทียมกันจะดำเนินการโดยซูเปอร์คลาสเท่านั้น คุณสามารถทำได้โดยดำเนินการ การดำเนินinstanceof
การ มิฉะนั้น เมื่อซีแมนทิกส์ของการตรวจสอบเปลี่ยนแปลงไปขึ้นอยู่กับคลาสที่ได้รับและการใช้งานเมธอดจำเป็นต้องย้ายลงตามลำดับชั้น คุณต้องใช้getClass()
เมธอด ในทางกลับกัน Joshua Bloch เสนอที่จะละทิ้งมรดกและใช้องค์ประกอบของวัตถุโดยรวมColorPoint
คลาส ในคลาส Point
และจัดเตรียมวิธีการเข้าถึงasPoint()
เพื่อรับข้อมูลเฉพาะเกี่ยวกับประเด็นนั้น วิธีนี้จะหลีกเลี่ยงการฝ่าฝืนกฎทั้งหมด แต่ในความคิดของฉัน มันจะทำให้โค้ดเข้าใจยากขึ้น ตัวเลือกที่สามคือการใช้การสร้างวิธีเท่ากับโดยอัตโนมัติโดยใช้ IDE อย่างไรก็ตาม Idea จะสร้างรุ่น Horstmann ขึ้นมาใหม่ ทำให้คุณสามารถเลือกกลยุทธ์สำหรับการนำวิธีการไปประยุกต์ใช้ในซูเปอร์คลาสหรือในรุ่นต่อๆ ไป ในที่สุด กฎ ความสอดคล้อง ถัดไป ระบุว่า แม้ว่าวัตถุ จะ x
ไม่y
เปลี่ยนแปลง การเรียกวัตถุเหล่านั้นอีกครั้งx.equals(y)
จะต้องส่งกลับค่าเดิมเหมือนเมื่อก่อน กฎข้อสุดท้ายคือไม่มีวัตถุใดควรจะnull
เท่ากับ ทุกอย่างชัดเจนที่นี่null
- นี่คือความไม่แน่นอน วัตถุเท่ากับความไม่แน่นอนหรือไม่? มันไม่ชัดเจนนั่นคือfalse
.
อัลกอริธึมทั่วไปสำหรับการกำหนดความเท่าเทียมกัน
- ตรวจสอบความเท่าเทียมกันของการอ้างอิงวัตถุ
this
และพารามิเตอร์วิธีo
การif (this == o) return true;
- ตรวจสอบว่าลิงก์ถูกกำหนดไว้
o
หรือไม่ เช่น ไม่ว่าจะnull
เป็น
หากในอนาคต เมื่อเปรียบเทียบประเภทออบเจ็กต์ จะใช้ตัวดำเนินการinstanceof
รายการนี้ก็สามารถข้ามได้ เนื่องจากพารามิเตอร์นี้จะส่งกลับในfalse
กรณีนี้null instanceof Object
- เปรียบเทียบประเภทวัตถุ
this
โดยใช้o
ตัวดำเนินการinstanceof
หรือวิธีการgetClass()
ตามคำอธิบายข้างต้นและสัญชาตญาณของคุณเอง - ถ้าเมธอด
equals
ถูกแทนที่ในคลาสย่อย อย่าลืมทำการโทรsuper.equals(o)
- แปลงประเภทพารามิเตอร์
o
เป็นคลาสที่ต้องการ - ทำการเปรียบเทียบฟิลด์ออบเจ็กต์ที่มีนัยสำคัญทั้งหมด:
- สำหรับประเภทดั้งเดิม (ยกเว้น
float
และdouble
) โดยใช้ตัวดำเนินการ==
- สำหรับฟิลด์อ้างอิง คุณต้องเรียกใช้เมธอดของมัน
equals
- สำหรับอาร์เรย์ คุณสามารถใช้การวนซ้ำหรือวิธีการได้
Arrays.equals()
- สำหรับประเภท
float
และdouble
จำเป็นต้องใช้วิธีการเปรียบเทียบของคลาส wrapper ที่เกี่ยวข้องFloat.compare()
และDouble.compare()
- สำหรับประเภทดั้งเดิม (ยกเว้น
- และสุดท้าย ตอบคำถามสามข้อ: วิธีการนำไปใช้มีความสมมาตรหรือไม่ สกรรมกริยา ? ตกลงไหม? อีกสองหลักการ ( การสะท้อนกลับและความแน่นอน ) มักจะดำเนินการโดยอัตโนมัติ
กฎการแทนที่ HashCode
แฮชคือตัวเลขที่สร้างขึ้นจากออบเจ็กต์ที่อธิบายสถานะ ณ จุดใดจุดหนึ่ง หมายเลขนี้ใช้ใน Java เป็นหลักในตารางแฮช เช่นHashMap
. ในกรณีนี้ ต้องใช้ฟังก์ชันแฮชในการรับตัวเลขตามออบเจ็กต์เพื่อให้แน่ใจว่ามีการกระจายองค์ประกอบในตารางแฮชค่อนข้างสม่ำเสมอ และเพื่อลดโอกาสที่จะเกิดการชนกันเมื่อฟังก์ชันส่งคืนค่าเดียวกันสำหรับคีย์ที่ต่างกัน
แฮชโค้ดของสัญญา
หากต้องการใช้ฟังก์ชันแฮช ข้อกำหนดภาษาจะกำหนดกฎต่อไปนี้:- การเรียกเมธอด
hashCode
หนึ่งครั้งขึ้นไปบนออบเจ็กต์เดียวกันจะต้องส่งคืนค่าแฮชเดียวกัน โดยมีเงื่อนไขว่าฟิลด์ของออบเจ็กต์ที่เกี่ยวข้องกับการคำนวณค่าไม่เปลี่ยนแปลง - การเรียกเมธอด
hashCode
บนอ็อบเจ็กต์ทั้งสองควรส่งคืนหมายเลขเดียวกันเสมอหากอ็อบเจ็กต์มีค่าเท่ากัน (การเรียกเมธอดequals
บนอ็อบเจ็กต์เหล่านี้จะส่งกลับtrue
) - การเรียกเมธอด
hashCode
บนอ็อบเจ็กต์ที่ไม่เท่ากันสองตัวจะต้องส่งคืนค่าแฮชที่แตกต่างกัน แม้ว่าข้อกำหนดนี้จะไม่ได้บังคับ แต่ก็ควรพิจารณาว่าการใช้งานจะมีผลเชิงบวกต่อประสิทธิภาพของตารางแฮช
วิธีการเท่ากับและ hashCode จะต้องถูกแทนที่ร่วมกัน
ตามสัญญาที่อธิบายไว้ข้างต้น จะตามมาว่าเมื่อแทนที่วิธีการในโค้ดของคุณequals
คุณจะต้องแทนที่วิธีการนั้นhashCode
เสมอ เนื่องจากในความเป็นจริง อินสแตนซ์สองอินสแตนซ์ของคลาสแตกต่างกันเนื่องจากอยู่ในพื้นที่หน่วยความจำที่แตกต่างกัน จึงต้องเปรียบเทียบตามเกณฑ์เชิงตรรกะบางประการ ดังนั้นวัตถุที่เทียบเท่ากันทางลอจิคัลสองตัวจะต้องส่งคืนค่าแฮชเดียวกัน จะเกิดอะไรขึ้นหากมีการแทนที่วิธีใดวิธีหนึ่งเหล่านี้
-
equals
ใช่hashCode
ไม่ใช่สมมติว่าเรากำหนดวิธีการ
equals
ในชั้นเรียนของเราอย่างถูกต้อง และhashCode
ตัดสินใจที่จะปล่อยให้วิธีการนั้นอยู่ในชั้นObject
เรียน จากนั้นจากมุมมองของวิธีการequals
วัตถุทั้งสองจะเท่ากันในเชิงตรรกะ ในขณะที่จากมุมมองของวิธีการ วัตถุทั้งสองhashCode
จะไม่มีอะไรที่เหมือนกัน ดังนั้นการวางวัตถุไว้ในตารางแฮชจะทำให้เราเสี่ยงที่จะไม่ได้รับวัตถุนั้นกลับมาด้วยคีย์
ตัวอย่างเช่นเช่นนี้:Map<Point, String> m = new HashMap<>(); m.put(new Point(1, 1), “Point A”); // pointName == null String pointName = m.get(new Point(1, 1));
แน่นอนว่าวัตถุที่ถูกวางและวัตถุที่กำลังค้นหานั้นเป็นวัตถุสองชิ้นที่แตกต่างกัน แม้ว่าพวกมันจะเท่ากันในเชิงตรรกะก็ตาม แต่เพราะว่า พวกเขามีค่าแฮชที่แตกต่างกันเนื่องจากเราละเมิดสัญญา เราสามารถพูดได้ว่าเราสูญเสียวัตถุของเราไปที่ไหนสักแห่งในลำไส้ของตารางแฮช
-
hashCode
ใช่equals
ไม่ใช่.จะเกิดอะไรขึ้นถ้าเราแทนที่เมธอด
hashCode
และ รับค่าการนำเมธอด ไปequals
ใช้งานจากคลาสObject
ดังที่คุณทราบequals
วิธีการเริ่มต้นเพียงเปรียบเทียบพอยน์เตอร์กับออบเจ็กต์ เพื่อพิจารณาว่าพวกมันอ้างถึงออบเจ็กต์เดียวกันหรือไม่ สมมติว่าhashCode
เราได้เขียนวิธีการตามหลักปฏิบัติทั้งหมด กล่าวคือ สร้างขึ้นโดยใช้ IDE และมันจะส่งคืนค่าแฮชเดียวกันสำหรับวัตถุที่เหมือนกันในเชิงตรรกะ แน่นอนว่าด้วยการทำเช่นนั้น เราได้กำหนดกลไกบางอย่างสำหรับการเปรียบเทียบวัตถุสองชิ้นไว้แล้วดังนั้นในทางทฤษฎีควรยกตัวอย่างจากย่อหน้าก่อนหน้า แต่เรายังไม่สามารถค้นหาวัตถุของเราในตารางแฮชได้ แม้ว่าเราจะอยู่ใกล้สิ่งนี้ แต่อย่างน้อยที่สุดเราจะพบตะกร้าตารางแฮชที่วัตถุจะวางอยู่
เพื่อให้ค้นหาวัตถุในตารางแฮชได้สำเร็จ นอกเหนือจากการเปรียบเทียบค่าแฮชของคีย์แล้ว ยังใช้การกำหนดความเท่าเทียมกันเชิงตรรกะของคีย์กับวัตถุที่ค้นหาด้วย นั่นคือ
equals
ไม่มีทางทำได้โดยไม่ลบล้างวิธีการนั้น
อัลกอริทึมทั่วไปสำหรับการกำหนด hashCode
สำหรับฉันแล้ว ดูเหมือนว่าคุณไม่ควรกังวลมากเกินไปและสร้างวิธีการใน IDE ที่คุณชื่นชอบ เพราะการเลื่อนบิตทั้งหมดไปทางขวาและซ้ายเพื่อค้นหาอัตราส่วนทองคำนั่นคือ การกระจายแบบปกติ - นี่มีไว้สำหรับคนหัวแข็งโดยสมบูรณ์ โดยส่วนตัวแล้วฉันสงสัยว่าฉันจะทำได้ดีและเร็วกว่าไอเดียเดียวกันหรือไม่แทนที่จะได้ข้อสรุป
ดังนั้นเราจะเห็นว่าวิธีการequals
มีhashCode
บทบาทที่ชัดเจนในภาษา Java และได้รับการออกแบบมาเพื่อให้ได้คุณลักษณะความเท่าเทียมกันเชิงตรรกะของวัตถุทั้งสอง ในกรณีของวิธีการequals
นี้มีความสัมพันธ์โดยตรงกับการเปรียบเทียบวัตถุ ในกรณีของhashCode
ทางอ้อม สมมติว่าจำเป็น เพื่อกำหนดตำแหน่งโดยประมาณของวัตถุในตารางแฮชหรือโครงสร้างข้อมูลที่คล้ายกันเพื่อที่จะ เพิ่มความเร็วในการค้นหาวัตถุ นอกจากสัญญาแล้วequals
ยังhashCode
มีข้อกำหนดอื่นที่เกี่ยวข้องกับการเปรียบเทียบวัตถุอีกด้วย นี่คือความสอดคล้องของ วิธี compareTo
อินเทอร์เฟComparable
ซกับไฟล์equals
. ข้อกำหนดนี้กำหนดให้นักพัฒนาต้องกลับมาเสมอx.equals(y) == true
เมื่อ x.compareTo(y) == 0
นั่นคือ เราเห็นว่าการเปรียบเทียบเชิงตรรกะของสองวัตถุไม่ควรขัดแย้งกันที่ใดก็ได้ในแอปพลิเคชัน และควรสอดคล้องกันเสมอ
GO TO FULL VERSION