[Java] 올바른 Map Iteration

zl존석동

·

2022. 1. 23. 13:40

 

Java 에서 Map 을 반복할 때 상황에 맞는 올바른 방법에 대해 알아보자

분명히 나만 몰랐을 것이다! 

사소한 것이지만 정리하고 넘어가고자 한다.


 

 

 

 

개요

 

알고리즘 문제를 풀던 뭘 하던 늘 하던대로 Map을 반복했었는데 코드분석 플러그인에서 경고를 보게 되었다.

 

sonarlint

 

 

경고를 받았던 코드의 예시

 

        Map<String, Integer> map = new HashMap<>();
        map.put("Hello", 25);
        map.put("Hell", 18);
        for (String str : map.keySet()) {
            System.out.println(str + map.get(str));
        }

 

Key, Value 를 루프문에서 모두 필요로 할 때 EntrySet으로 반복하라는 경고 메시지를 받았다.

 

 

 

 

Key,Value 모두 사용할 때의 Non-Compliant 

 

 public void doSomethingWithMap(Map<String,Object> map) {    
 	for (String key : map.keySet()) { 
    	// Noncompliant; for each key the value is retrieved      
        Object value = map.get(key);  
    }  
}

 

Map으로부터 KeySet 을 불러와 또 map의 get(Key) 를 통해 value 를 찾게 된다.

 

키를 통해 맵으로부터 값을 조회하는 작업을 한번 더 하기 때문에 비효율적이고 최악의 경우 O(n) 의 복잡도를 가미하게 된다고 한다.

 

 

 

 

Key,Value 모두 사용할때의 Compliant 

 

public void doSomethingWithMap(Map<String,Object> map) {    
	for (Map.Entry<String,Object> entry : map.entrySet()) {      
    	String key = entry.getKey();      
        Object value = entry.getValue();      // ...    
    }  
}

 

EntrySet 을 사용해 루프를 돌면 Key, Value를 세트로 하여 참조 가능하기 때문에

 

key로 한번더 값을 조회하는 작업을 할 필요가 없게 된다.

 

 

 

 

Key 또는 Value 만 사용하는 적절한 예시

 

        for (int value : map.values()) {
            System.out.println(value + "값");
        }
        // 값만 필요할 때
        for (String str : map.keySet()) {
            System.out.println(str + "키");
        }

 

오히려 Key 또는 Value 만 필요할 경우에는 다음과 같이 반복을 돌 때 성능에 더 도움이 된다고 한다.

 

 

 

 

성능 비교하기

 

// map size: 5000000     

// key,value 모두 사용하는 잘못된 반복
    static void hashLoopNonCompliant(){
        for(String keys: hs.keySet()){
            res1 += hs.get(keys);
        }
    }

// key,value 모두 사용하는 옳은 반복
    static void hashLoopCompliant(){
        for(Map.Entry<String,Integer> entry : hs.entrySet()){
            res2 += entry.getValue();
        }
    }

// value 만 사용하는 반복
    static void hashLoopValues(){
        for(Integer values : hs.values()){
            res3 += values;
        }
    }

 

 

 

 

결론

 

 

key, value 모두 사용하는 반복을 할 때는 Entry entrySet() 을 이용하자!

 

keySet을 불러와 .get(key) 로 값을 다시 찾지 말자!

 

 

 

 

 

ref

 

 

Java static code analysis | Code Smell: Methods returns should not be invariant

When a method is designed to return an invariant value, it may be poor design, but it shouldn’t adversely affect the outcome of your program. However, when it happens on all paths through the logic, it is surely a bug. This rule raises an issue when a me

rules.sonarsource.com

 

예전에 사실 정리해보았던 내용인데 잊었던 것 같아 한번 더 정리해보았다!

 

나만 몰랐던 Java Map Iteration

Baby Dev who wannabe Harder Better Faster Stronger

pds0309.github.io

 

 

'Java' 카테고리의 다른 글

[java] Reflection  (0) 2022.02.14
[Java] ConcurrentModificationException 해결하기  (0) 2022.02.04
[Java] 예외란 뭘까  (0) 2022.01.10
[Java] Abstract , Interface  (0) 2022.01.09
[Java] 람다식이란  (0) 2022.01.06