Map을 for 문 돌리는 방법은 여러가지가 있을텐데, 사람마다 사용하는 방식이 다양하다.
몇몇 코드를 보다가 차이가 얼마나 나나 의문이 들어서 비교 테스트를 해보았다.
테스트를 위해 HashMap 을 이용했다.
기본 Map 구성. 100만건 랜덤하게 구성
Map<String, Integer> testMap = new HashMap<>(); for (int idx = 0; idx < 10000000; idx++) { testMap.put(RandomStringUtils.random(10, true, true), RandomUtils.nextInt()); }
특별한 일은 하지 않고, 3가지 방법으로 for문을 돌리는 데에만 집중했다.
* keySet Iterator 을 이용
* keySet 을 이용
* entrySet 을 이용
long start = System.currentTimeMillis(); Iterator<String> keyIter = testMap.keySet().iterator(); int count = 0; while (keyIter.hasNext()) { String key = keyIter.next(); count++; } System.out.println("startTime = " + start + ", executeTime = " + (System.currentTimeMillis() - start)); start = System.currentTimeMillis(); Set<String> keySet = testMap.keySet(); for (String key : keySet) { count++; } System.out.println("startTime = " + start + ", executeTime = " + (System.currentTimeMillis() - start)); start = System.currentTimeMillis(); for (Entry<String, Integer> entry : testMap.entrySet()) { count++; } System.out.println("startTime = " + start + ", executeTime = " + (System.currentTimeMillis() - start));그랬더니..
startTime = 1478674524129, executeTime = 375 startTime = 1478674524505, executeTime = 374 startTime = 1478674524879, executeTime = 344 |
long timeStart1, timeStart2, timeStart3; long time1, time2, time3; timeStart1 = System.currentTimeMillis(); Iterator<String> keyIter = testMap.keySet().iterator(); while (keyIter.hasNext()) { String key = keyIter.next(); System.out.println("key = " + key + ", value = " + testMap.get(key)); } time1 = System.currentTimeMillis() - timeStart1; timeStart2 = System.currentTimeMillis(); Set<String> keySet = testMap.keySet(); for (String key : keySet) { System.out.println("key = " + key + ", value = " + testMap.get(key)); } time2 = System.currentTimeMillis() - timeStart2; timeStart3 = System.currentTimeMillis(); for (Entry<String, Integerg> entry : testMap.entrySet()) { System.out.println("key = " + entry.getKey() + ", value = " + entry.getValue()); } time3 = System.currentTimeMillis() - timeStart3; System.out.println("startTime = " + timeStart1 + ", executeTime = " + time1); System.out.println("startTime = " + timeStart2 + ", executeTime = " + time2); System.out.println("startTime = " + timeStart3 + ", executeTime = " + time3);
startTime = 1478680748403, executeTime = 67023 startTime = 1478680815426, executeTime = 57720 startTime = 1478680873146, executeTime = 55663 |
그냥 testMap.get(key) 혹은, entry.getValue() 만 호출 했을 때,
startTime = 1478681425373, executeTime = 616 startTime = 1478681425989, executeTime = 605 startTime = 1478681426594, executeTime = 418 |
startTime = 1478681960603, executeTime = 594 startTime = 1478681961197, executeTime = 607 startTime = 1478681961804, executeTime = 397 |
startTime = 1478682044013, executeTime = 591 startTime = 1478682044604, executeTime = 610 startTime = 1478682045214, executeTime = 399 |
startTime = 1478682072837, executeTime = 606 startTime = 1478682073443, executeTime = 612 startTime = 1478682074055, executeTime = 399 |
startTime = 1478682102417, executeTime = 627 startTime = 1478682103044, executeTime = 632 startTime = 1478682103676, executeTime = 511 |
startTime = 1478682189217, executeTime = 619 startTime = 1478682189836, executeTime = 661 startTime = 1478682190497, executeTime = 413 |
startTime = 1478682190910, executeTime = 652 startTime = 1478682191562, executeTime = 641 startTime = 1478682192203, executeTime = 439 |
startTime = 1478682192642, executeTime = 648 startTime = 1478682193290, executeTime = 665 startTime = 1478682193955, executeTime = 431 |
startTime = 1478682241011, executeTime = 589 startTime = 1478682241600, executeTime = 595 startTime = 1478682242195, executeTime = 401 |
startTime = 1478682242596, executeTime = 651 startTime = 1478682243247, executeTime = 563 startTime = 1478682243810, executeTime = 402 |
보통은, print 를 하지 않고 value 를 참조하기만 하니, 맨 마지막 결과의 차이가 실제 체감하는 속도 차이일 것 같다.
keySet Iterator 나 keySet 이나 비슷하다. Set<String> 을 기반으로 돌면서, hash 참조해서 value 를 얻어오는 것.
for loop 를 돌 때, EntrySet 을 이용하는 것이 효율적이다.
다만, Map 에 data 양이 그리 많지 않을 경우, 체감할 만큼 차이는 별로 없었다.
API 소스를 구석구석 보았지만, EntrySet 이 어떻게 구성되는지, 왜 속도 차이가 나는지 완벽하게 이해를 못했다.
대강 이해를 한 것 같지만,, 뭔가 찜찜하다.
지나다 보신 고수 분들 명쾌한 가르침 부탁드립니다..
'스터디 > 자바' 카테고리의 다른 글
제12회 한국자바개발자 컨퍼런스 (0) | 2012.01.29 |
---|---|
이클립스 could not open jvm.cfg file error (2) | 2010.07.25 |