Hashtables มอบวิธีที่เป็นประโยชน์ในการเพิ่มประสิทธิภาพการทำงานของแอปพลิเคชัน
Hashtables ไม่ใช่แนวคิดใหม่ในสาขาคอมพิวเตอร์ ได้รับการออกแบบมาเพื่อเร่งความเร็วการประมวลผลของคอมพิวเตอร์ ซึ่งช้ามากตามมาตรฐานปัจจุบัน และช่วยให้คุณค้นหารายการเฉพาะได้อย่างรวดเร็วเมื่อทำการสืบค้นรายการข้อมูลจำนวนมาก แม้ว่าเครื่องจักรสมัยใหม่จะเร็วขึ้นหลายพันเท่า แต่แฮชเทเบิลก็ยังเป็นเครื่องมือที่มีประโยชน์ในการรับประสิทธิภาพที่ดีที่สุดจากแอปพลิเคชันของคุณ
ลองจินตนาการว่าคุณมีไฟล์ข้อมูลประมาณหนึ่งพันบันทึก เช่น บันทึกลูกค้าสำหรับธุรกิจขนาดเล็ก และโปรแกรมที่อ่านบันทึกลงในหน่วยความจำเพื่อประมวลผล แต่ละบันทึกประกอบด้วยหมายเลขประจำตัวลูกค้าห้าหลัก ชื่อลูกค้า ที่อยู่ ยอดคงเหลือในบัญชี ฯลฯ สมมติว่าเรกคอร์ดไม่ได้เรียงลำดับตามหมายเลขรหัสลูกค้า ดังนั้น หากโปรแกรมต้องการใช้หมายเลขลูกค้าเป็น "คีย์" เพื่อค้นหาเรกคอร์ดลูกค้ารายใดรายหนึ่ง วิธีเดียวที่จะค้นหาคือค้นหาแต่ละเรกคอร์ดติดต่อกัน บางครั้งมันจะค้นหาเรคคอร์ดที่คุณต้องการอย่างรวดเร็ว แต่บางครั้ง ก่อนที่โปรแกรมจะพบเรคคอร์ดที่คุณต้องการ มันก็เกือบจะค้นหาเรคคอร์ดสุดท้ายแล้ว หากคุณต้องการค้นหาจาก 1,000 รายการ การค้นหารายการใดรายการหนึ่งจำเป็นต้องให้โปรแกรมตรวจสอบรายการเฉลี่ย 500.5 ((1000 + 1)/2) หากคุณต้องการค้นหาข้อมูลบ่อยครั้ง คุณอาจต้องการวิธีที่รวดเร็วกว่าในการค้นหาเรกคอร์ด
วิธีหนึ่งที่จะช่วยให้การค้นหาของคุณเร็วขึ้นคือการแบ่งบันทึกออกเป็นชิ้นๆ เพื่อว่าแทนที่จะค้นหารายการใหญ่เพียงรายการเดียว คุณจะค้นหารายการสั้นๆ หลายๆ รายการได้ สำหรับหมายเลขรหัสลูกค้าที่เป็นตัวเลขของเรา คุณสามารถสร้างได้ 10 รายการ - หนึ่งรายการสำหรับหมายเลข ID ที่ขึ้นต้นด้วย 0, หนึ่งรายการสำหรับหมายเลข ID ที่ขึ้นต้นด้วย 1 และอื่นๆ ดังนั้นหากต้องการค้นหาหมายเลขรหัสลูกค้า 38016 คุณเพียงแค่ค้นหารายการที่ขึ้นต้นด้วย 3 เท่านั้น หากมี 1,000 เรคคอร์ด และความยาวเฉลี่ยของแต่ละรายการคือ 100 (1,000 เรคคอร์ดแบ่งออกเป็น 10 รายการ) ดังนั้น จำนวนการเปรียบเทียบโดยเฉลี่ยเพื่อค้นหาเรคคอร์ดจะลดลงเหลือประมาณ 50 (ดูรูปที่ 1)
แน่นอนว่า หากลูกค้าประมาณหนึ่งในสิบเริ่มต้นด้วย 0 และอีกสิบคนที่เริ่มต้นด้วย 1 และอื่นๆ แนวทางนี้ก็ใช้ได้ผลดี หาก 90% ของหมายเลขลูกค้าเริ่มต้นด้วย 0 รายการนั้นก็จะมีเรกคอร์ด 900 รายการ ซึ่งต้องมีการเปรียบเทียบโดยเฉลี่ย 450 รายการต่อการค้นหา นอกจากนี้ 90% ของการค้นหาที่โปรแกรมจำเป็นต้องดำเนินการนั้นเป็นการค้นหาตัวเลขที่ขึ้นต้นด้วย 0 ดังนั้นจำนวนการเปรียบเทียบเฉลี่ยจึงอยู่นอกเหนือขอบเขตของการดำเนินการทางคณิตศาสตร์อย่างง่าย
จะดีกว่าถ้าเราสามารถแจกจ่ายบันทึกในรายการของเราในลักษณะที่แต่ละรายการมีรายการเดียวกัน โดยไม่คำนึงถึงการกระจายของตัวเลขในค่าคีย์ เราต้องการวิธีผสมผสานจำนวนลูกค้าเข้าด้วยกันและกระจายผลลัพธ์ได้ดีขึ้น ตัวอย่างเช่น เรานำตัวเลขแต่ละหลักมาคูณด้วยตัวเลขจำนวนมาก (ซึ่งแตกต่างกันไปขึ้นอยู่กับตำแหน่งของตัวเลข) บวกผลลัพธ์เพื่อให้ได้ผลรวม หารตัวเลขนี้ด้วย 10 แล้วให้ส่วนที่เหลือเป็นดัชนี ค่า (ดัชนี) เมื่อมีการอ่านบันทึก โปรแกรมจะรันฟังก์ชันแฮชนี้กับหมายเลขลูกค้าเพื่อพิจารณาว่ารายการใดเป็นของบันทึก เมื่อผู้ใช้ต้องการสอบถาม ฟังก์ชันแฮชเดียวกันจะถูกใช้เป็น "คีย์" สำหรับหมายเลขลูกค้า เพื่อให้สามารถค้นหารายการที่ถูกต้องได้ โครงสร้างข้อมูลเช่นนี้เรียกว่าแฮชเทเบิล
แฮชเทเบิลใน Java
Java มีสองคลาสคือ java.util.Hashtable และ java.util.HashMap ซึ่งมีกลไกแฮชเทเบิลอเนกประสงค์ ทั้งสองคลาสมีความคล้ายคลึงกันมากและโดยทั่วไปจะมีอินเทอร์เฟซสาธารณะที่เหมือนกัน แต่พวกเขามีความแตกต่างที่สำคัญบางประการ ซึ่งฉันจะพูดถึงในภายหลัง
ออบเจ็กต์ Hashtable และ HashMap ช่วยให้คุณสามารถรวมคีย์และค่า และป้อนคู่คีย์/ค่าลงในตารางโดยใช้เมธอด put () จากนั้นคุณสามารถรับค่าได้โดยการเรียกเมธอด get() โดยส่งคีย์เป็นพารามิเตอร์ คีย์และค่าสามารถเป็นออบเจ็กต์ใดก็ได้ตราบใดที่เป็นไปตามข้อกำหนดพื้นฐานสองประการ โปรดทราบว่าเนื่องจากคีย์และค่าต้องเป็นอ็อบเจ็กต์ ประเภทดั้งเดิมจึงต้องแปลงเป็นอ็อบเจ็กต์โดยใช้วิธีการ เช่น Integer(int)
เพื่อที่จะใช้วัตถุของคลาสเฉพาะเป็นคีย์ คลาสจะต้องมีสองวิธี คือ เท่ากับ() และ hashCode() สองเมธอดนี้อยู่ใน java.lang.Object ดังนั้นคลาสทั้งหมดจึงสามารถสืบทอดทั้งสองเมธอดนี้ได้ อย่างไรก็ตาม การใช้งานทั้งสองเมธอดในคลาส Object โดยทั่วไปแล้วไม่มีประโยชน์ ดังนั้น โดยปกติแล้วคุณจะต้องโอเวอร์โหลดเมธอดทั้งสองนี้ด้วยตัวเอง
วิธีการเท่ากับ () จะเปรียบเทียบวัตถุกับวัตถุอื่นและส่งคืนค่าจริงหากวัตถุทั้งสองแสดงข้อมูลเดียวกัน วิธีนี้ยังดูให้แน่ใจว่าวัตถุทั้งสองอยู่ในคลาสเดียวกัน Object.equals() คืนค่าเป็นจริงหากวัตถุอ้างอิงทั้งสองเป็นวัตถุที่เหมือนกัน ซึ่งอธิบายว่าทำไมโดยทั่วไปวิธีนี้จึงไม่เหมาะสม ในกรณีส่วนใหญ่ คุณต้องมีวิธีเปรียบเทียบเขตข้อมูลต่อเขตข้อมูล ดังนั้นเราจึงถือว่าออบเจ็กต์ต่างๆ ที่แสดงถึงข้อมูลเดียวกันมีความเท่าเทียมกัน
วิธีการ HashCode() สร้างค่า int โดยดำเนินการฟังก์ชันแฮชโดยใช้เนื้อหาของวัตถุ Hashtable และ HashMap ใช้ค่านี้เพื่อดูว่าคู่คีย์/ค่าอยู่ในที่เก็บข้อมูล (หรือรายการ) ใด
ตัวอย่างเช่น เราสามารถดูคลาส String ได้ เนื่องจากมีเมธอดของตัวเองที่ใช้ทั้งสองเมธอดนี้ String.equals() เปรียบเทียบวัตถุ String สองตัวอักขระต่ออักขระและส่งคืนค่าจริงหากสตริงเหมือนกัน:
คัดลอกรหัสรหัส ดังต่อไปนี้:
สตริง myName = "ไอน์สไตน์";
// การทดสอบต่อไปนี้คือ
//จริงเสมอ.
ถ้า ( myName.equals("ไอน์สไตน์") )
-
String.hashCode() รันฟังก์ชันแฮชบนสตริง รหัสตัวเลขของอักขระแต่ละตัวในสตริงจะคูณด้วย 31 และผลลัพธ์จะขึ้นอยู่กับตำแหน่งของอักขระในสตริง จากนั้นจึงนำผลลัพธ์ของการคำนวณเหล่านี้มารวมกันเพื่อให้ได้ผลรวม กระบวนการนี้อาจดูซับซ้อน แต่รับประกันการกระจายค่าที่ดีขึ้น นอกจากนี้ยังแสดงให้เห็นว่าคุณสามารถไปได้ไกลแค่ไหนเมื่อพัฒนาวิธีการ hashCode() ของคุณเอง โดยมั่นใจว่าผลลัพธ์จะไม่ซ้ำใคร
ตัวอย่างเช่น สมมติว่าฉันต้องการใช้แฮชเทเบิลเพื่อใช้แคตตาล็อกหนังสือ และใช้หมายเลข ISBN ของหนังสือเป็นคีย์การค้นหาในการค้นหา ฉันสามารถใช้คลาส String เพื่อนำรายละเอียดและเตรียมเมธอดเท่ากับ () และ hashCode() ให้พร้อม (ดูรายการ 1) เราสามารถเพิ่มคู่คีย์/ค่าให้กับ hashtable โดยใช้วิธี put () (ดูรายการ 2)
วิธี การ Put () ยอมรับพารามิเตอร์สองตัว ซึ่งทั้งสองตัวเป็นประเภท Object พารามิเตอร์ตัวแรกคือคีย์ พารามิเตอร์ตัวที่สองคือค่า เมธอด Put () เรียกเมธอด hashCode() ของคีย์ และหารผลลัพธ์ตามจำนวนรายการในตาราง ใช้ส่วนที่เหลือเป็นค่าดัชนีเพื่อกำหนดว่าจะเพิ่มระเบียนลงในรายการใด โปรดทราบว่าคีย์นั้นไม่ซ้ำกันในตาราง หากคุณเรียก put () ด้วยคีย์ที่มีอยู่ รายการที่ตรงกันจะถูกแก้ไขเพื่อให้อ้างอิงถึงค่าใหม่และค่าเก่าจะถูกส่งกลับ ( เมื่อคีย์ไม่มีอยู่ในตาราง , ใส่ () ส่งกลับค่า null)
หากต้องการอ่านค่าจากตาราง เราใช้คีย์ค้นหาพร้อมกับเมธอด get() มันจะส่งกลับการอ้างอิงวัตถุที่แปลงเป็นประเภทที่ถูกต้อง:
คัดลอกรหัสรหัส ดังต่อไปนี้:
BookRecord br =
(BookRecord)isbnTable.get(
"0-345-40946-9");
System.out.println(
"ผู้แต่ง: " + br.author
+ " ชื่อ: " + br.title);
วิธีที่มีประโยชน์อีกวิธีหนึ่งคือ Remove() ซึ่งใช้เกือบจะเหมือนกับ get() โดยจะลบรายการออกจากตารางและส่งกลับไปยังโปรแกรมที่เรียกใช้
ชั้นเรียนของคุณเอง
หากคุณต้องการใช้ประเภทดั้งเดิมเป็นคีย์ คุณต้องสร้างออบเจ็กต์ประเภทเดียวกัน ตัวอย่างเช่น หากคุณต้องการใช้คีย์จำนวนเต็ม คุณควรใช้ Constructor Integer(int) เพื่อสร้างออบเจ็กต์จากจำนวนเต็ม คลาส wrapper ทั้งหมด เช่น Integer, Float และ Boolean ถือว่าค่าดั้งเดิมเป็นอ็อบเจ็กต์ และพวกมันโอเวอร์โหลดเมธอดเท่ากับ () และ hashCode() ดังนั้นจึงสามารถใช้เป็นคีย์ได้ คลาสอื่นๆ จำนวนมากที่มีให้ใน JDK จะเป็นเช่นนี้ (แม้แต่คลาส Hashtable และ HashMap ก็ใช้วิธีการเท่ากับ() และ hashCode() ของตัวเอง) แต่คุณควรตรวจสอบเอกสารประกอบก่อนที่จะใช้อ็อบเจ็กต์ของคลาสใดๆ เป็นคีย์ hashtable นอกจากนี้ยังจำเป็นต้องตรวจสอบแหล่งที่มาของคลาสเพื่อดูว่ามีการใช้งานเท่ากับ () และ hashCode () อย่างไร ตัวอย่างเช่น ไบต์ อักขระ แบบสั้น และจำนวนเต็ม ล้วนส่งคืนค่าจำนวนเต็มที่แสดงเป็นโค้ดแฮช สิ่งนี้อาจจะใช่หรือไม่ตรงกับความต้องการของคุณก็ได้
การใช้ Hashtables ใน Java
หากคุณต้องการสร้างแฮชเทเบิลที่ใช้อ็อบเจ็กต์ของคลาสที่คุณกำหนดเป็นคีย์ คุณควรตรวจสอบให้แน่ใจว่าเมธอดเท่ากับ () และ hashCode() ของคลาสนั้นให้ค่าที่เป็นประโยชน์ ขั้นแรกให้ดูที่คลาสที่คุณขยายเพื่อพิจารณาว่าการใช้งานนั้นตรงตามความต้องการของคุณหรือไม่ ถ้าไม่เช่นนั้น คุณควรโอเวอร์โหลดวิธีการนี้
ข้อจำกัดการออกแบบพื้นฐานของเมธอดเท่ากับ () ก็คือควรคืนค่าเป็นจริงหากวัตถุที่ส่งไปให้นั้นเป็นของคลาสเดียวกันและฟิลด์ข้อมูลถูกตั้งค่าเป็นค่าที่แสดงถึงข้อมูลเดียวกัน คุณควรตรวจสอบให้แน่ใจด้วยว่าหากคุณส่งอาร์กิวเมนต์ว่างไปยังเมธอด โค้ดของคุณจะส่งกลับ
คัดลอกรหัสรหัส ดังต่อไปนี้:
เท็จ: บูลีนสาธารณะเท่ากับ (Object o)
-
ถ้า ( (o == โมฆะ)
||. !(หรืออินสแตนซ์ของ myClass))
-
กลับเท็จ;
-
// ตอนนี้เปรียบเทียบเขตข้อมูล...
นอกจากนี้ ยังมีกฎบางข้อที่คุณควรคำนึงถึงเมื่อออกแบบเมธอด hashCode() ขั้นแรก เมธอดจะต้องส่งคืนค่าเดียวกันสำหรับอ็อบเจ็กต์เฉพาะ ไม่ว่าจะเรียกใช้เมธอดกี่ครั้งก็ตาม (แน่นอน ตราบใดที่เนื้อหาของอ็อบเจ็กต์ไม่เปลี่ยนแปลงระหว่างการโทร เมื่อใช้อ็อบเจ็กต์เป็นคีย์แฮช สิ่งนี้ควร หลีกเลี่ยง) ประการที่สอง หากวัตถุสองชิ้นที่กำหนดโดยเมธอดเท่ากับ () ของคุณมีค่าเท่ากัน วัตถุทั้งสองนั้นจะต้องสร้างรหัสแฮชเดียวกันด้วย ประการที่สาม นี่เป็นแนวทางมากกว่าหลักการ คุณควรพยายามออกแบบวิธีการของคุณเพื่อให้ผลลัพธ์ที่แตกต่างกันสำหรับเนื้อหาวัตถุที่แตกต่างกัน ไม่สำคัญว่าบางครั้งวัตถุที่แตกต่างกันจะสร้างรหัสแฮชเดียวกันหรือไม่ อย่างไรก็ตาม หากเมธอดสามารถส่งคืนค่าในช่วง 1 ถึง 10 เท่านั้น ก็สามารถใช้ได้เพียง 10 รายการเท่านั้น ไม่ว่าจะมีกี่รายการในแฮชเทเบิลก็ตาม
อีกปัจจัยที่ต้องคำนึงถึงเมื่อออกแบบเท่ากับ() และ hashCode() ก็คือประสิทธิภาพ การเรียกแต่ละครั้งเพื่อ ใส่ () หรือ get() เกี่ยวข้องกับการเรียก hashCode() เพื่อค้นหารายการที่ถูกต้อง เมื่อ get() สแกนรายการเพื่อค้นหาคีย์ มันจะเรียกเท่ากับ() สำหรับแต่ละองค์ประกอบในรายการ นำวิธีการเหล่านี้ไปใช้เพื่อให้ทำงานได้อย่างรวดเร็วและมีประสิทธิภาพที่สุดเท่าที่จะเป็นไปได้ โดยเฉพาะอย่างยิ่งหากคุณวางแผนที่จะทำให้ชั้นเรียนของคุณพร้อมใช้งานแบบสาธารณะ เนื่องจากผู้ใช้รายอื่นอาจต้องการใช้ชั้นเรียนของคุณในแอปพลิเคชันประสิทธิภาพสูงที่ความเร็วในการดำเนินการเป็นสิ่งสำคัญ
ประสิทธิภาพที่สามารถแฮชได้
ปัจจัยหลักที่ส่งผลต่อประสิทธิภาพของแฮชเทเบิลคือความยาวเฉลี่ยของรายการในตาราง เนื่องจากเวลาในการค้นหาโดยเฉลี่ยเกี่ยวข้องโดยตรงกับความยาวเฉลี่ยนี้ แน่นอนว่าในการลดความยาวเฉลี่ย คุณต้องเพิ่มจำนวนรายการใน hashtable คุณจะได้รับประสิทธิภาพการค้นหาที่ดีที่สุด หากจำนวนรายการมีขนาดใหญ่จนรายการส่วนใหญ่หรือทั้งหมดมีเพียงระเบียนเดียว อย่างไรก็ตาม นี่อาจจะไปไกลเกินไป หากแฮชเทเบิลของคุณมีรายการมากกว่ารายการข้อมูล คุณก็ไม่จำเป็นต้องเสียค่าใช้จ่ายด้านหน่วยความจำดังกล่าว และในบางกรณีก็เป็นไปไม่ได้ที่คนอื่นจะยอมรับแนวทางนี้
ในตัวอย่างก่อนหน้านี้ เรารู้ล่วงหน้าว่าเรามีบันทึกจำนวนเท่าใด 1,000 เมื่อทราบสิ่งนี้แล้ว เราก็สามารถตัดสินใจได้ว่าควรมีรายการแฮชเทเบิลจำนวนเท่าใดเพื่อให้เกิดประนีประนอมที่ดีที่สุดระหว่างความเร็วในการค้นหาและประสิทธิภาพการใช้งานหน่วยความจำ อย่างไรก็ตาม ในหลายกรณี คุณไม่ทราบล่วงหน้าว่าคุณจะประมวลผลบันทึกจำนวนเท่าใด ไฟล์ที่อ่านข้อมูลอาจเพิ่มขึ้นอย่างต่อเนื่อง หรือจำนวนบันทึกอาจเปลี่ยนแปลงอย่างมากในแต่ละวัน
คลาส Hashtable และ HashMap จัดการปัญหานี้โดยการขยายตารางแบบไดนามิกเมื่อมีการเพิ่มรายการ ทั้งสองคลาสมีคอนสตรัคเตอร์ที่ยอมรับจำนวนรายการเริ่มต้นในตาราง และปัจจัยโหลดเป็นพารามิเตอร์:
Hashtable สาธารณะ (
int ความจุเริ่มต้น,
ปัจจัยโหลดลอยตัว)
HashMap สาธารณะ (
int ความจุเริ่มต้น,
ปัจจัยโหลดลอยตัว)
คูณตัวเลขสองตัวนี้เพื่อคำนวณค่าวิกฤต แต่ละครั้งที่มีการเพิ่มรายการใหม่ลงในตารางแฮช จำนวนจะได้รับการอัปเดต และเมื่อจำนวนเกินค่าวิกฤต ตารางจะถูกรีเซ็ต (แฮชใหม่) (ขนาดรายการเพิ่มขึ้นเป็นสองเท่าของขนาดก่อนหน้าบวก 1 และรายการทั้งหมดจะถูกย้ายไปยังรายการที่ถูกต้อง) ตัวสร้างเริ่มต้นตั้งค่าความจุเริ่มต้นเป็น 11 และปัจจัยการโหลดเป็น 0.75 ดังนั้นค่าวิกฤตคือ 8 เมื่อเพิ่มบันทึกที่เก้าลงในตาราง ตารางแฮชจะถูกปรับขนาดใหม่เพื่อให้มี 23 รายการ และค่าวิกฤตใหม่จะเป็น 17 (ส่วนจำนวนเต็ม 23*0.75) คุณจะเห็นว่าปัจจัยการโหลดเป็นขอบเขตบนของจำนวนรายการโดยเฉลี่ยในตารางแฮช ซึ่งหมายความว่าตามค่าเริ่มต้น ตารางแฮชแทบจะไม่มีรายการจำนวนมากที่มีมากกว่าหนึ่งระเบียน เปรียบเทียบตัวอย่างเดิมของเรา ซึ่งเรามีบันทึก 1,000 รายการกระจายอยู่ใน 10 รายการ หากเราใช้ค่าเริ่มต้น ตารางนี้จะขยายให้มีมากกว่า 1,500 รายการ แต่คุณสามารถควบคุมสิ่งนี้ได้ หากจำนวนรายการคูณด้วยตัวประกอบภาระงานมากกว่าจำนวนรายการที่คุณกำลังประมวลผล ตารางจะไม่ถูกสร้างใหม่ ดังนั้นเราจึงสามารถทำตามตัวอย่างด้านล่าง:
คัดลอกรหัสรหัส ดังต่อไปนี้:
// ตารางจะไม่ทำการแฮชใหม่จนกว่าจะถึงตอนนั้น
// มี 1,100 รายการ (10*110):
แฮชเทเบิล myHashTable =
ใหม่ Hashtable (10, 110.0F);
คุณอาจไม่ต้องการทำเช่นนี้ เว้นแต่คุณไม่ต้องการบันทึกหน่วยความจำสำหรับรายการว่าง และไม่สนใจเวลาในการค้นหาเพิ่มเติม ซึ่งอาจเกิดขึ้นได้ในระบบสมองกลฝังตัว อย่างไรก็ตาม วิธีการนี้อาจมีประโยชน์เนื่องจากการรีเซ็ตมีราคาแพงในการคำนวณ และวิธีนี้ช่วยให้แน่ใจว่าการรีเซ็ตจะไม่เกิดขึ้น
โปรดทราบว่าแม้ว่าการเรียก put () อาจทำให้ตารางขยายใหญ่ขึ้น (เพิ่มจำนวนรายการ) แต่การเรียก Remove() จะไม่ให้ผลตรงกันข้าม ดังนั้น หากคุณมีตารางขนาดใหญ่และลบรายการส่วนใหญ่ออกจากตาราง คุณจะจบลงด้วยตารางขนาดใหญ่แต่ส่วนใหญ่ว่างเปล่า
Hashtable และ HashMap
มีความแตกต่างที่สำคัญสามประการระหว่างคลาส Hashtable และ HashMap ความแตกต่างประการแรกคือเหตุผลทางประวัติศาสตร์เป็นหลัก Hashtable ขึ้นอยู่กับคลาส Dictionary เก่า และ HashMap เป็นการใช้งานอินเทอร์เฟซ แผนที่ ที่นำมาใช้ใน Java 1.2
บางทีความแตกต่างที่สำคัญที่สุดก็คือเมธอดของ Hashtable เป็นแบบซิงโครนัส ในขณะที่เมธอดของ HashMap ไม่ใช่ ซึ่งหมายความว่า แม้ว่าคุณจะสามารถใช้ Hashtable ในแอปพลิเคชันแบบมัลติเธรดได้โดยไม่ต้องดำเนินการใดๆ เป็นพิเศษ แต่คุณจะต้องจัดให้มีการซิงโครไนซ์ภายนอกสำหรับ HashMap ในทำนองเดียวกัน วิธีที่สะดวกคือการใช้เมธอด synchronizedMap() แบบคงที่ของคลาส Collections ซึ่งสร้างออบเจ็กต์ Map ที่ปลอดภัยสำหรับเธรด และส่งกลับเป็นออบเจ็กต์ที่ห่อหุ้ม วิธีการของวัตถุนี้ช่วยให้คุณเข้าถึง HashMap พื้นฐานได้พร้อมกัน ผลลัพธ์ก็คือ คุณไม่สามารถตัดการซิงโครไนซ์ใน Hashtable ได้ เมื่อคุณไม่ต้องการมัน (เช่น ในแอปพลิเคชันแบบเธรดเดียว) และการซิงโครไนซ์จะเพิ่มค่าใช้จ่ายในการประมวลผลจำนวนมาก
ข้อแตกต่างประการที่สามคือมีเพียง HashMap เท่านั้นที่อนุญาตให้คุณใช้ค่า Null เป็นคีย์หรือค่าของรายการตาราง มีเพียงระเบียนเดียวใน HashMap ที่สามารถเป็นคีย์ว่างได้ แต่จำนวนรายการเท่าใดก็ได้ก็สามารถเป็นค่าว่างได้ ซึ่งหมายความว่าหากไม่พบคีย์การค้นหาในตาราง หรือหากพบคีย์การค้นหาแต่เป็นค่าว่าง ดังนั้น get() จะส่งกลับค่าว่าง หากจำเป็น ให้ใช้เมธอดtainKey() เพื่อแยกความแตกต่างระหว่างสองสถานการณ์
ข้อมูลบางอย่างแนะนำว่าเมื่อจำเป็นต้องมีการซิงโครไนซ์ ให้ใช้ Hashtable มิฉะนั้นให้ใช้ HashMap อย่างไรก็ตาม เนื่องจาก HashMap สามารถซิงโครไนซ์ได้เมื่อจำเป็น HashMap จึงมีฟังก์ชันมากกว่า Hashtable และไม่ได้ขึ้นอยู่กับคลาสเก่า บางคนจึงคิดว่า HashMap เป็นที่นิยมมากกว่า Hashtable ในสถานการณ์ต่างๆ
เกี่ยวกับคุณสมบัติ
บางครั้งคุณอาจต้องการใช้แฮชเทเบิลเพื่อจับคู่สตริงคีย์กับสตริงค่า มีตัวอย่างสตริงสภาพแวดล้อมใน DOS, Windows และ Unix ตัวอย่างเช่น คีย์สตริง PATH ถูกแมปกับสตริงค่า C:/WINDOWS;C:/WINDOWS/SYSTEM Hashtables เป็นวิธีง่ายๆ ในการแสดงสิ่งเหล่านี้ แต่ Java จัดเตรียมวิธีอื่นไว้
คลาส Java .util.Properties เป็นคลาสย่อยของ Hashtable ที่ออกแบบมาเพื่อใช้กับคีย์และค่าสตริง การใช้ออบเจ็กต์ Properties นั้นคล้ายคลึงกับการใช้ Hashtable แต่คลาสจะเพิ่มวิธีการประหยัดเวลาสองวิธีที่คุณควรรู้
Store() วิธีการบันทึกเนื้อหาของวัตถุคุณสมบัติไปยังไฟล์ในรูปแบบที่อ่านได้ เมธอด Load() ตรงกันข้าม ใช้สำหรับอ่านไฟล์และตั้งค่าออบเจ็กต์ Properties ให้มีคีย์และค่า
โปรดทราบว่าเนื่องจากคุณสมบัติขยาย Hashtable คุณจึงสามารถใช้เมธอด put () ของซูเปอร์คลาสเพื่อเพิ่มคีย์และค่าที่ไม่ใช่ออบเจ็กต์ String ได้ สิ่งนี้ไม่แนะนำให้เลือก นอกจากนี้ หากคุณใช้ store() กับวัตถุ Properties ที่ไม่มีวัตถุ String store() จะล้มเหลว อีกทางเลือกหนึ่งในการ ใส่ () และ get() คุณควรใช้ setProperty() และ getProperty() ซึ่งรับพารามิเตอร์ String
โอเค ฉันหวังว่าคุณจะรู้วิธีใช้แฮชเทเบิลเพื่อเร่งการประมวลผลของคุณแล้ว