[TIL] 항해99 65일차

심우진·2021년 11월 22일
0

해시맵(HashMap)

  • key와 value를 하나의 쌍(entry)으로 저장되는 구조이며, 해싱(hashing)을 사용하기 때문에 많은 양의 데이터를 검색하는데 있어 뛰어난 성능을 보인다.
  • 저장되는 key와 value는 null 값을 허용한다. 단, key는 중복 불가하다. (즉, null 을 가지는 key 는 2개일 수 없다)
  • key, value의 쌍으로 관리하므로, Iteration 객체를 사용하지 않고 해당 key에서 데이터의 값을 바로 추출할 수 있다.
  • 동기화가 포함되지 않으므로, 멀티 스레드 환경에서의 구현이 아니라면 HashTable에 비해 처리 속도가 빠르다.
  • List와 달리, Map에는 순서가 없다.
  • 유사한 성격의 클래스로는 HashTable, TreeMap 등이 있다.

HashMap의 주요 메소드

HashMap 1. put/get

put() 메소드를 이용하여 데이터를 key, value 의 쌍으로 저장하고, get() 메소드를 통해 값을 꺼내올 수 있다.

Map<String, String> map = new HashMap<String, String>();
    
    //add value
    map.put("a", "A");
    map.put("a", "AA");
    map.put("b", "B");
    map.put("c", "C");
    map.put(null, "NullValue");
    
    //get value
    System.out.println(map.get("a"));
    System.out.println(map.get("d"));
    System.out.println(map.get(null));

출력값:
AA
null
NullValue

HashMap 2. containsKey/containsValue

map 안에 해당 key / value 가 있는지 확인하는 메소드이다. boolean 타입으로 값을 반환한다.

Map<String, String> map = new HashMap<String, String>();
        
    //add value
    map.put("a", "A");
    map.put("a", "AA");
    map.put("b", "B");
    map.put("c", "C");
    map.put(null, "NullValue");
        
    //check if key/
    System.out.println(map.containsKey("a"));
    System.out.println(map.containsValue("Z"));

출력값:
true
false

HashMap 3. keySet()/values()/entrySet() 으로 전체출력

keySet()은 map에서 key 만을 가져올 때, valuse()는 value 만을 가져올 때,
그리고 entrySet()은 키와 값을 모두 가져올 때 사용한다. 주로 반복문을 돌려 전체 출력/검색 시에 사용한다.

Map<String, String> map = new HashMap<String, String>();
        
    //add value        
    map.put("a", "A");
    map.put("a", "AA");
    map.put("b", "B");
    map.put("c", "C");
    map.put(null, "NullValue");
    
    //iteration 
    for (String key : map.keySet()) {
        System.out.print(map.get(key) + "/");
    }
        
    for (Map.Entry<String, String> entry : map.entrySet()) {
        System.out.print(entry + "/");
    }

출력값:
NullValue/AA/B/C/
null=NullValue/a=AA/b=B/c=C/

HashMap 4. replace() - 값 변경

map에 담겨있는 데이터의 값을 변경할 때 사용한다. replace(key, value) 메소드로는 해당 key 에 해당하는 값을 바로 바꾸어주며, replace(key, oldValue, newValue) 메소드는 해당 key에 oldValue 값이 있을 때에만 값을 대체한다.

    //replace
    System.out.println("map_before: "+ map);        
    System.out.println(map.replace("a", "AA", "Z"));
    System.out.println("map_after: "+ map);

출력값:
map_before: {null=NullValue, a=AA, b=B, c=C}
true
map_after: {null=NullValue, a=Z, b=B, c=C}

HashMap 5. getOrDefault(), putIfAbsent(), computeIfAbesent(), computeIfPresent()

getOrDefault(): key 값이 없다면 입력 시 설정한 default 값을 반환. 단, 해당 값이 map에 저장되지는 않는다.
putIfAbsent(): 해당 key가 있으나 없으나 get한다. (key 값이 없다면 입력 된 key와 value 를 입력, 해당 key가 존재하면 입력 되었던 값 반환).
computeIfAbsent(): 해당 key가 있으면 get 하고, 없으면 put 한다.
computeIfPresent(): 해당 key가 있으면 해당 메소드를 호출하여 (값을 변경, 변경된 value 값으로) 다시 put 한다. 키가 없으면 메소드를 호출하지 않는다.

Map<String, String> map = new HashMap<String, String>();
        map.put("apple", "apple");
        map.put("banana", "banana");
        map.put("mango", "mango");
        
        //getOrDefault(): key가 없으면 default로 설정한 값을 출력
        System.out.println("getOrDefault(): " + map.getOrDefault("apple", "lemon"));
        System.out.println("getOrDefault(): " + map.getOrDefault("lemon", "lemon"));
        System.out.println("values in map: "+ map);
        
        //putIfAbsent(): 값이 비어있으면 해당 메소드의 value("lemon")을 put 함. 단, 이전 값이 존재하지 않기 때문에 null 반환
        map.putIfAbsent("lemon", "lemon");
        System.out.println("values in map: "+ map);
        
        //key로 된 값이 없을 때 put 하는 것이기 때문에 이미 값이 있을 경우 value("orange")로 대체하지 않음. 
        map.putIfAbsent("lemon", "orange");        
        System.out.println("values in map: "+ map);

출력값:
getOrDefault(): apple
getOrDefault(): lemon
values in map: {banana=banana, apple=apple, mango=mango}
values in map: {banana=banana, apple=apple, lemon=lemon, mango=mango}
values in map: {banana=banana, apple=apple, lemon=lemon, mango=mango}

computeIfAbsent() 는 key값이 없을 때 메소드를 호출하며, 이미 존재하면 해당 메소드를 호출하지 않는다. 하지만, putIfAbsent()는 key값의 존재 여부와 상관없이 메소드를 호출한다. computeIfPresent() 는 key값이 존재할 때 메소드를 호출하며, 그렇지 않으면 해당 메소드를 호출하지 않는다. computeIfPresent 메서드는 key와 remapping function 두개의 인자를 갖는다. 그래서 key가 있을 때만 value를 변환한다.

Map<String, String> map = new HashMap<String, String>();
        map.put("apple", "apple");
        map.put("banana", "banana");
        map.put("mango", "mango");
        
        //computeIfAbsent(): key값이 없을 때 메소드를 호출한다.         
        map.computeIfAbsent("kiwi", key -> pm.setFruit(key));
        System.out.println("values in map: "+ map);
        
        //putIfAbsent(): key값이 이미 존재해도 메소드는 호출된다. 단, 이 경우 apple 이라는 키에는 이미 값이 있기 때문에, value가 변경되지 않는다. 
        map.putIfAbsent("apple", pm.setFruit("red apple"));
        System.out.println("values in map: "+ map);
 
        //computeIfPresent(): key값이 존재할 때 메소드를 호출한다.  
        map.computeIfPresent("kiwi", (String key, String value) -> "gold "+value);
        System.out.println("values in map: "+ map);

위 예제의 setFruit()은 key 값을 리턴하는 간단한 메소드이다. computeIfAbsent() / computeIfPresent() 메소드가 실행될 경우, map에 데이터가 저장되는 것을 확인할 수 있다.

출력값:
values in map: {banana=banana, apple=apple, kiwi=kiwi, lemon=lemon, mango=mango}
values in map: {banana=banana, apple=apple, kiwi=kiwi, lemon=lemon, mango=mango}
values in map: {banana=banana, apple=apple, kiwi=gold kiwi, lemon=lemon, mango=mango}

0개의 댓글