ใน Java อะไรคือความแตกต่างระหว่าง IdentityHashMap และ HashMap + การเปรียบเทียบประสิทธิภาพ
เผยแพร่แล้ว: 2021-10-19
บางครั้งฉันมีกรณีพิเศษที่ฉันต้องเปรียบเทียบคีย์ของแผนที่ตาม equality operator (==)
ตัวดำเนินการความเท่าเทียมกัน (==) จะเปรียบเทียบการอ้างอิง (ที่อยู่ในหน่วยความจำ) ของคีย์ทั้งสองเป็นตัวเลขที่แตกต่างกันสองหมายเลข
ในทางกลับกัน HashMap เป็นองค์ประกอบ Java Collection Framework ที่ใช้มากที่สุด ซึ่งเปรียบเทียบความเป็นเอกลักษณ์ของคีย์ด้วยความช่วยเหลือของวิธี equals()
นอกจากนี้ IdentityHashMap
ไม่ได้ใช้แฮชจาก object.hashCode()
แต่ใช้ System.identityHashCode(object)
เราสามารถใช้ IdentityHashMap สำหรับอ็อบเจ็กต์ที่เปลี่ยนแปลงได้ซึ่งโค้ดแฮชเปลี่ยนระหว่างรันไทม์
หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับ equals()
และ ==
ซึ่งใช้ on String Object
ให้ทำตามบทช่วยสอนนี้: https://crunchify.com/how-to-override-equals-and-hashcode-method-in-java/
การทดสอบพื้นฐานซึ่งแสดงให้เห็นข้างต้นเท่ากับ () และ == พฤติกรรม:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
package crunchify . com . tutorials ; import java . util . HashMap ; import java . util . IdentityHashMap ; import java . util . Map ; /** * @author Crunchify.com * */ public class CrunchifyIdenityHashMapVsHashMapSample { public static void main ( String [ ] args ) { Map < String , String > crunchifyIdentityHashMap = new IdentityHashMap < String , String > ( ) ; Map < String , String > crunchifyHashMap = new HashMap < String , String > ( ) ; // Let's checkout what happens when we put Unique Key to IdentityHashMap crunchifyIdentityHashMap . put ( "Company" , "Crunchify" ) ; // this considered different object for == operator crunchifyIdentityHashMap . put ( new String ( "Company" ) , "Google" ) ; crunchifyIdentityHashMap . put ( "Company" , "Facebook" ) ; System . out . println ( "crunchifyIdentityHashMap KeySet Size: " + crunchifyIdentityHashMap . keySet ( ) . size ( ) ) ; // Let's checkout what happens when we put Unique Key to HashMap crunchifyHashMap . put ( "Company" , "Crunchify" ) ; // key1.equals(key2) returns true hence it removes the old value crunchifyHashMap . put ( new String ( "Company" ) , "Google" ) ; crunchifyHashMap . put ( "Company" , "Facebook" ) ; System . out . println ( "crunchifyHashMap KeySet Size: " + crunchifyHashMap . keySet ( ) . size ( ) ) ; } } |
ผลลัพธ์:
1 2 |
crunchifyIdentityHashMap KeySet Size : 2 crunchifyHashMap KeySet Size : 1 |
มาทำการทดสอบประสิทธิภาพบนทั้งสองแผนที่กัน:
- สร้างคลาส Java:
CrunchifyIdentityHashMapVsHashMapPerformance
.java
-
startCrunchifyTest()
- สร้างขนาดแผนที่สุ่มเป็นล้าน
- สร้างอินสแตนซ์และเริ่มต้น
crunchifyString[]
วัตถุสตริงอาร์เรย์ด้วยหมายเลขสุ่มที่สร้างด้านบนพร้อมข้อความ:This is Crunchify's Test # number
-
crunchifyCompareIdentityHashMapVsHashMap(String[] crunchifyString , Map<String, Integer> crunchifyMap , String name )
- ส่งพารามิเตอร์ที่จำเป็นทั้งหมดไปยังวิธีนี้
-
crunchifyMap
จะมีค่า IdentityHashMap / HashMap - ทำซ้ำผ่าน crunchifyString[] และใส่ค่าลงใน Map — การดำเนินการนี้ใช้เวลาพอสมควร
- ทำซ้ำผ่าน crunchifyString[] และรับค่าจาก Map — การดำเนินการนี้ใช้เวลาพอสมควร
- เราจะหาเวลาดำเนินการสำหรับการดำเนินการทั้งสองข้างต้นเพื่อเปรียบเทียบว่าอันไหนดีกว่าสำหรับการดำเนินการข้างต้น IdentityHashMap หรือ HashMap
- พิมพ์ด้านบนผล
- ดำเนินการข้างต้นงาน 2 และ 3 รวม 8 ครั้ง
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
package crunchify . com . tutorials ; import java . util . HashMap ; import java . util . IdentityHashMap ; import java . util . Map ; import java . util . Random ; /** * @author Crunchify.com * */ public class CrunchifyIdentityHashMapVsHashMapPerformance { static Random rand = new Random ( ) ; private static void startCrunchifyTest ( ) { // Let's run test for 5 times for ( int i = 0 ; i < 15 ; ++ i ) { // Let's create random Map size which we will use in IdentityHashMap and HashMap int randomMapSize = 1000000 + rand . nextInt ( 9000000 ) ; String [ ] crunchifyString = new String [ randomMapSize ] ; for ( int j = 0 ; j < randomMapSize ; ++ j ) // Assign below string to crunchifyString Object crunchifyString [ j ] = "This is Crunchify's Test #" + j ; System . out . println ( "\nIteration # " + i + " - Creating String with size: " + randomMapSize ) ; crunchifyCompareIdentityHashMapVsHashMap ( crunchifyString , new HashMap < String , Integer > ( randomMapSize ) , "HashMap" ) ; // Runs the garbage collector System . gc ( ) ; crunchifyCompareIdentityHashMapVsHashMap ( crunchifyString , new IdentityHashMap < String , Integer > ( randomMapSize ) , "IdentityHashMap" ) ; // Runs the garbage collector System . gc ( ) ; } } /** * @param crunchifyString * @param crunchifyMap * : IdentityHashMap / HashMap * @param name */ private static void crunchifyCompareIdentityHashMapVsHashMap ( String [ ] crunchifyString , Map < String , Integer > crunchifyMap , String name ) { long start = System . currentTimeMillis ( ) ; // put crunchifyString String[] to map for ( int put = 0 ; put < crunchifyString . length ; ++ put ) crunchifyMap . put ( crunchifyString [ put ] , put ) ; boolean result = false ; for ( int get = 0 ; get < crunchifyString . length ; ++ get ) { if ( crunchifyMap . get ( crunchifyString [ get ] ) ! = get ) result = true ; } System . out . println ( name + " time taken : \t" + ( System . currentTimeMillis ( ) - start ) / 1000. + " sec" ) ; // Check for result discrepancy if ( crunchifyMap . size ( ) ! = crunchifyString . length ) System . out . println ( "Please check size. Test failed" ) ; if ( result ) System . out . println ( "Result failed.." ) ; } public static void main ( String [ ] args ) { System . out . println ( "IdentityHashMap Vs. HashMap comparison Test started..." ) ; // method to compare IdentityHashMap and HashMap startCrunchifyTest ( ) ; } } |
ผลลัพธ์:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
IdentityHashMap Vs . HashMap comparison Test started . . . Iteration # 0 - Creating String with size: 6964175 HashMap time taken : 3.155 sec IdentityHashMap time taken : 1.517 sec Iteration # 1 - Creating String with size: 6556459 HashMap time taken : 3.415 sec IdentityHashMap time taken : 1.466 sec < == IdentityHashMap gives better result for large object Iteration # 2 - Creating String with size: 9567664 HashMap time taken : 4.173 sec IdentityHashMap time taken : 2.339 sec < == better Iteration # 3 - Creating String with size: 4230755 HashMap time taken : 0.372 sec IdentityHashMap time taken : 0.911 sec Iteration # 4 - Creating String with size: 7821718 HashMap time taken : 1.096 sec IdentityHashMap time taken : 0.812 sec Iteration # 5 - Creating String with size: 8125421 HashMap time taken : 4.883 sec IdentityHashMap time taken : 1.876 sec < == better Iteration # 6 - Creating String with size: 3166432 HashMap time taken : 0.537 sec IdentityHashMap time taken : 0.708 sec Iteration # 7 - Creating String with size: 2821415 HashMap time taken : 0.227 sec IdentityHashMap time taken : 0.621 sec |
การสังเกต:
ดังที่คุณเห็นในผลลัพธ์นี้ สำหรับแผนที่ขนาดใหญ่ IdentityHashMap จะทำงานได้ดีกว่ามาก ทำไม? IdentityHashMap doesn't use equals() and hashcode() methods
ซึ่งถือว่ามีค่าใช้จ่ายสูง

เพียงแค่ FYI:
การดำเนินการข้างต้นที่เราทำเพื่อใส่และรับค่าจากและลงใน Map นั้นใช้ CPU มาก
