Set in Java เป็นชุดที่ไม่มีองค์ประกอบที่ซ้ำกันหรือจะแม่นยำคู่องค์ประกอบที่ไม่มี E1.equals (E2) NULL ได้รับอนุญาตในชุด ชุดไม่สามารถรับประกันลำดับขององค์ประกอบในชุด
เมื่อเพิ่มองค์ประกอบที่จะตั้งค่าหากองค์ประกอบที่ระบุไม่มีอยู่การเพิ่มจะสำเร็จ นั่นคือถ้าองค์ประกอบ E1 ไม่มีอยู่ในชุด (e == null? e1 == null: E.Queals (E1)) ดังนั้นสามารถเพิ่ม E1 ลงในชุดได้
นี่คือตัวอย่างการใช้งานที่ตั้งค่าไว้เป็นตัวอย่างและแนะนำหลักการของการตั้งค่าให้ไม่ใช้ซ้ำในการดำเนินการซ้ำ:
แพ็คเกจ com.darren.test.overide; customstring คลาสสาธารณะ {ค่าสตริงส่วนตัว; public customstring () {this (");} public customstring (ค่าสตริง) {this.value = value;}} แพ็คเกจ com.darren.test.overide; นำเข้า java.util.hashset; นำเข้า java.util.set; คลาสสาธารณะ hashSettest {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {สตริง a = สตริงใหม่ ("a"); สตริง b = สตริงใหม่ ("a"); CustomString ("B"); System.out.println ("A.Equals (B) ==" + A.Equals (B)); System.out.println ("C.Equals (D) ==" + C.Equals (D)) hashset <jobch> (); set.add (a); set.add (b); set.add (c); set.add (d); system.out.println ("set.size () ==" + set.size ()); สำหรับ (วัตถุ: set) {system.out.println (วัตถุ);ผลการดำเนินการมีดังนี้:
a.equals (b) == true c.equals (d) == false set.size () == 3 com.darren.test.overide.customstring@2c39d2 a com.darren.test.overide.customstring@5795ce
บางทีคุณอาจเคยเห็นกุญแจที่ถูกต้องมันเป็นวิธีที่เท่าเทียมกัน มันยังไม่เหมาะสมที่จะพูดแบบนี้ แต่เพื่อความแม่นยำควรเป็นวิธีการเท่ากับและ hashcode ทำไมคุณถึงพูดแบบนั้น? ลองเปลี่ยนคลาส CustomString และทดสอบ:
แพ็คเกจ com.darren.test.overide; คลาสสาธารณะ customstring {ค่าสตริงส่วนตัว; public customstring () {this (");} public customstring (ค่าสตริง) {this.value = value;}@override public boolean (object obj) obj; return customstring.value.equals (value);} else {return false;}}}ผลการทดสอบ:
A.Equals (B) == True C.Equals (D) == True set.size () == 3 com.darren.test.overide.customstring@12504e0 a com.darren.test.overide.customstring@1630EB6
ค่าส่งคืนเท่ากับเวลานี้เป็นจริง แต่ขนาดของชุดยังคงเป็น 3
ลองเปลี่ยนกันต่อไป
แพ็คเกจ com.darren.test.overide; customstring คลาสสาธารณะ {ค่าสตริงส่วนตัว; Public CustomString () {this (");} Public CustomString (ค่าสตริง) {this.value = value;}@แทนที่ int hashCode () {// return.hashCode (); return 1;}}ดูผลลัพธ์อีกครั้ง:
A.Equals (B) == True C.Equals (D) == FALSE SET.SIZE () == 3 com.darren.test.overide.customstring@1 com.darren.test.overide.customstring@1 A
เฉพาะวิธีการเขียน hashcode ใหม่เท่านั้นไม่ใช่การเขียนอีกครั้ง
ในที่สุดเปลี่ยนมัน
แพ็คเกจ com.darren.test.overide; คลาสสาธารณะ customstring {ค่าสตริงส่วนตัว; public customstring () {this (");} public customstring (ค่าสตริง) {this.value = value;}@override public boolean (object obj) obj; return customstring.value.equals (value);} else {return false;}}@reverride public int hashCode () {// return super.hashCode (); return 1;}}ผลลัพธ์สุดท้าย:
A.Equals (b) == True C.Equals (D) == True set.size () == 2 com.darren.test.overide.customstring@1 A
ตกลงมันได้รับการพิสูจน์แล้วว่าคุณต้องเขียนวิธี Equals และวิธีการ HashCode ใหม่และดูหลักการ:
อนุสัญญาสำหรับ HashCode ใน java.lnag.Object:
1. ในระหว่างการดำเนินการของแอปพลิเคชันหากข้อมูลที่ใช้ในการเปรียบเทียบวิธี Equals ของวัตถุไม่ได้รับการแก้ไขวิธีการ HashCode จะเรียกว่าหลายครั้งในวัตถุและจะต้องส่งคืนจำนวนเต็มเดียวกันอย่างต่อเนื่อง
2. หากวัตถุทั้งสองมีค่าเท่ากันตามวิธี Equals (ObjectO) การเรียกใช้วิธี HashCode ของวัตถุทั้งสองวัตถุทั้งสองจะต้องสร้างผลลัพธ์จำนวนเต็มเดียวกัน
3. หากวัตถุทั้งสองไม่เท่ากันตามวิธี Equals (ObjectO) ดังนั้นวิธีการ HashCode ของวัตถุทั้งสองของทั้งสองจะถูกเรียกและไม่จำเป็นต้องมีผลลัพธ์จำนวนเต็มที่แตกต่างกัน แต่ถ้ามันแตกต่างกันมันอาจปรับปรุงประสิทธิภาพของตารางแฮช
ใน HashSet การดำเนินการขั้นพื้นฐานจะถูกนำไปใช้โดยเลเยอร์ HashMap เนื่องจาก HashSet Layer ใช้ HashMap เพื่อจัดเก็บข้อมูล เมื่อเพิ่มองค์ประกอบลงใน Hashset ให้คำนวณค่าแฮชโฟตอนแรกขององค์ประกอบจากนั้นใช้สิ่งนี้ (hashcode ขององค์ประกอบ)% (ขนาดของคอลเลกชัน HashMap) + 1 เพื่อคำนวณตำแหน่งการจัดเก็บขององค์ประกอบนี้ หากตำแหน่งนี้ว่างเปล่าให้เพิ่มองค์ประกอบ หากไม่ว่างเปล่าให้ใช้วิธี Equals เพื่อเปรียบเทียบว่าองค์ประกอบนั้นเท่ากันและถ้าเท่ากันก็เท่ากันอย่าเพิ่มมันมิฉะนั้นจะหาพื้นที่ว่างเพื่อเพิ่ม
ต่อไปนี้เป็นส่วนหนึ่งของซอร์สโค้ดของ HashSet:
แพ็คเกจ java.util; Hashset คลาสสาธารณะ <E> ขยายบทคัดย่อ <e> ใช้ชุด <e>, cloneable, java.io.serializable {คงที่สุดท้าย Long SerialVersionUid = -502444406713321676L; // HashMap ชั่วคราว <e, Object> MAP; // กำหนดวัตถุวัตถุเสมือนจริงเป็นค่าของ HashMap และกำหนดวัตถุนี้เป็นแบบคงที่ วัตถุสุดท้ายคงที่ส่วนตัวนำเสนอ = new Object ();/*** ตัวสร้างพารามิเตอร์เริ่มต้นสร้างแฮชเซ็ตที่ว่างเปล่า * * ในความเป็นจริงเลเยอร์พื้นฐานจะเริ่มต้น HashMap ที่ว่างเปล่าและใช้ความจุเริ่มต้นเริ่มต้นที่ 16 และปัจจัยการโหลด 0.75 */public hashset () {map = new hashmap <e, object> ();}/*** สร้างชุดใหม่ที่มีองค์ประกอบในคอลเลกชันที่ระบุ * * เลเยอร์พื้นฐานที่เกิดขึ้นจริงใช้ปัจจัยการโหลดเริ่มต้น 0.75 และเพียงพอที่จะมีความจุเริ่มต้นขององค์ประกอบทั้งหมดในคอลเลกชัน * ที่ระบุเพื่อสร้าง hashmap * @param C องค์ประกอบในนั้นจะถูกเก็บไว้ในคอลเลกชันในชุดนี้ */hashset สาธารณะ (คอลเลกชัน <ขยาย e> c) {map = new hashmap <e, object> (math.max ((int) (c.size ()/. 75f) + 1, 16)); addall (c);}/*** สร้าง hashset ว่างเปล่า * * เลเยอร์พื้นฐานที่เกิดขึ้นจริงสร้าง HashMap ที่ว่างเปล่าพร้อมพารามิเตอร์ที่สอดคล้องกัน * @param ความจุเริ่มต้นความจุเริ่มต้น * @param loadfactor factor factor */hashset สาธารณะ (int initialcapacity, float loadfactor) {map = new hashmap <e, object> (การเริ่มต้นการเริ่มต้น, loadfactor);}/*** สร้าง hashset ที่ว่างเปล่าด้วยการเริ่มต้นที่ระบุ * * ในความเป็นจริงเลเยอร์พื้นฐานจะสร้าง hashmap ที่ว่างเปล่าด้วยพารามิเตอร์ที่สอดคล้องกันและโหลดปัจจัยโหลด 0.75 * @param ความจุเริ่มต้นความจุเริ่มต้น */public hashset (int initialcapacity) {map = new hashmap <e, object> (initialcapacity);}/*** สร้างคอลเลกชันแฮชลิงค์ว่างเปล่าใหม่ด้วยการเริ่มต้นที่ระบุและ loadfactor * ตัวสร้างนี้ได้รับอนุญาตการเข้าถึงแพ็คเกจและไม่ได้สัมผัสกับสาธารณะ จริงๆแล้วมันเป็นเพียงการสนับสนุนสำหรับ LinkedHashSet * * ในความเป็นจริงเลเยอร์พื้นฐานจะสร้างอินสแตนซ์ LinkedHashMap ที่ว่างเปล่าด้วยพารามิเตอร์ที่ระบุเพื่อนำไปใช้งาน * @param ความจุเริ่มต้นความจุเริ่มต้น * @param loadfactor factor factor * @param dummy tag */hashset (int initialcapacity, float loadfactor, boolean dummy) {map = new LinkedHashMap <e, Object> (การเริ่มต้นความสามารถ, loadfactor);}/*** ส่งคืนตัววนซ้ำที่ทำซ้ำองค์ประกอบในชุดนี้ ลำดับขององค์ประกอบผลตอบแทนไม่ได้เฉพาะเจาะจง * * เลเยอร์พื้นฐานจริง ๆ เรียกคีย์เซ็ตของ HashMap พื้นฐานเพื่อส่งคืนคีย์ทั้งหมด * องค์ประกอบใน HashSet สามารถมองเห็นได้ แต่จะถูกเก็บไว้ในกุญแจของ HashMap พื้นฐานและค่าจะถูกระบุโดยวัตถุวัตถุสุดท้าย * @return iterator ที่วนซ้ำองค์ประกอบในชุดนี้ */@Override Public Public Iterator <e> iterator () {return map.keyset (). iterator ();}/*** ส่งคืนจำนวนองค์ประกอบในชุดนี้ (ความสามารถของชุด) * * เลเยอร์พื้นฐานเรียกใช้วิธี Size () ของ HashMap เพื่อส่งคืนจำนวนรายการและรับจำนวนองค์ประกอบในชุด * @กลับมาจำนวนองค์ประกอบในชุดนี้ (ความสามารถของชุด) */@Override Public Public Size () {return map.size ();}/*** ส่งคืนจริงถ้าชุดนี้ไม่มีองค์ประกอบใด ๆ * * เลเยอร์พื้นฐานการเรียกใช้ isempty () ของ hashmap เพื่อตรวจสอบว่าแฮชเซ็ตว่างเปล่าหรือไม่ * @return ส่งคืนจริงถ้าชุดนี้ไม่มีองค์ประกอบใด ๆ */@แทนที่บูลีนสาธารณะ isempty () {return map.isempty ();}/*** ส่งคืนจริงถ้าชุดนี้มีองค์ประกอบที่ระบุ * โดยเฉพาะอย่างยิ่งจริงจะถูกส่งคืนหากชุดนี้มีองค์ประกอบ e ที่เป็นไปตาม (o == null? e == null: o.equals (e)) * * * The ContainsKey ของการเรียกใช้จริงที่เกิดขึ้นจริงไปยัง HASHMAP กำหนดว่ามีคีย์ที่ระบุหรือไม่ * @param o การมีอยู่ขององค์ประกอบในชุดนี้ได้รับการทดสอบแล้ว * @return ส่งคืนจริงถ้าชุดนี้มีองค์ประกอบที่ระบุ */@การแทนที่บูลีนสาธารณะมี (Object O) {return map.containsKey (O);}/*** หากองค์ประกอบที่ระบุไม่รวมอยู่ในชุดนี้เพิ่มองค์ประกอบที่ระบุ * โดยเฉพาะอย่างยิ่งหากชุดนี้ไม่มีองค์ประกอบ E2 ที่ตอบสนอง (e == null? e2 == null: e.equals (e2)) * องค์ประกอบที่ระบุจะถูกเพิ่มเข้าไปในชุดนี้ * หากชุดนี้มีองค์ประกอบอยู่แล้วการโทรจะไม่เปลี่ยนชุดและส่งคืนเท็จ * * เลเยอร์พื้นฐานจะทำให้องค์ประกอบเป็นคีย์ลงใน HashMap * เนื่องจากวิธีการของ HashMap's Put () เพิ่มคู่คีย์-ค่าเมื่อคีย์ในรายการใหม่ของ HashMap * เป็นคีย์ของรายการต้นฉบับในคอลเลกชัน (HashCode () จะส่งคืนค่าเท่ากัน * ดังนั้นหากมีการเพิ่มองค์ประกอบที่มีอยู่ใน HashSet องค์ประกอบคอลเลกชันที่เพิ่มเข้ามาใหม่จะไม่ถูกใส่ลงใน HashMap และ * องค์ประกอบดั้งเดิมจะไม่เปลี่ยนแปลงใด ๆ ซึ่งเป็นไปตามคุณสมบัติของการไม่ซ้ำขององค์ประกอบในชุด * องค์ประกอบ @param e ที่จะเพิ่มในชุดนี้ * @return ส่งคืนจริงถ้าชุดนี้ไม่มีองค์ประกอบที่ระบุ */@การแทนที่บูลีนสาธารณะเพิ่ม (e e) {return map.put (e, ปัจจุบัน) == null;}/*** หากองค์ประกอบที่ระบุมีอยู่ในชุดนี้จะถูกลบออก * โดยเฉพาะอย่างยิ่งหากชุดนี้มีองค์ประกอบ e ที่เป็นไปตาม (o == null? e == null: o.equals (e)), * จะลบออก ส่งคืนจริงถ้าชุดนี้มีองค์ประกอบอยู่แล้ว (หรือ: จริงหากชุดนี้เปลี่ยนแปลงเนื่องจากการโทร) (เมื่อการโทรกลับมาชุดนี้จะไม่มีองค์ประกอบอีกต่อไป) * * เลเยอร์พื้นฐานเรียกใช้วิธีการลบของ HASHMAP เพื่อลบรายการที่ระบุ * @param o วัตถุที่ต้องลบออกหากมีอยู่ในชุดนี้ * @return ส่งคืนจริงถ้าชุดมีองค์ประกอบที่ระบุ */@การแทนที่บูลีนสาธารณะลบ (Object O) {return map.remove (o) == ปัจจุบัน;}/*** ลบองค์ประกอบทั้งหมดออกจากชุดนี้ หลังจากการโทรกลับมาชุดจะว่างเปล่า * * เลเยอร์พื้นฐานเรียกใช้วิธีการที่ชัดเจนของ HashMap เพื่อล้างองค์ประกอบทั้งหมดในรายการ */@Override Public Void Clear () {map.clear ();}}สรุป
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้เกี่ยวกับการวิเคราะห์หลักการของการกำจัด hashset ของค่าที่ซ้ำกัน ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน เพื่อนที่สนใจสามารถอ้างถึงหัวข้ออื่น ๆ ที่เกี่ยวข้องในเว็บไซต์นี้ต่อไป หากมีข้อบกพร่องใด ๆ โปรดฝากข้อความไว้เพื่อชี้ให้เห็น ขอบคุณเพื่อนที่ให้การสนับสนุนเว็บไซต์นี้!