딱 하루

오늘이 내게 남은 단 하루인 것 처럼

스터디/자바

Map for loop 속도 비교

eJungHyun 2016. 11. 9. 19:05
반응형

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



결과가 차이가 남. 
그냥 for문 돌면서 카운트만 더해줬는데, Entry 로 for문 돌린 것과 차이가 있음.

그래서, value 를 가져오면 얼마나 차이가 날까 싶어 비교를 해보았더니,

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);

결과는,

System.out 찍었을 때,

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