Studying/자료구조

Hashmap 자료구조

aoaa 2022. 5. 12. 16:32

 

 해시맵은 Map 인터페이스에 속해있는 Collection으로, 데이터들을 Key와 Value로 구성된 entry 객체를 저장하는 자료구조입니다. 여기서 key는 고유한 속성이지만, Value는 고유한 속성이 아니기 때문에 Value는 중복이 될 수 있습니다. Hash는 특정 키에 대한 값을 빠르게 찾아올 수 있는 장점이 있습니다. key-value가 1:1로 매칭되기 때문에 삽입, 삭제, 검색 과정에서 O(1)의 시간복잡도를 가집니다.

 


1.  Hashmap 선언

import java.util.HashMap; 
public class Test {
	public static void main(String[] args) { 
    HashMap hm = new HashMap(); // 타입 설정x Object 입력 
    HashMap<Integer, Integer> i = new HashMap<>(); // Integer, Integer 타입 설정 
    HashMap<Integer, Integer> i2 = new HashMap<>(i); // i의 값을 i2에 카피 
    HashMap<Integer, Integer> i3 = new HashMap<>(10); // 초기용량 지정 
    HashMap<Integer, Integer> i4 = new HashMap<>() {{ // 변수 선언 + 초기값 지정 put(1, 100);
    put(2, 200); }}; 
    
    HashMap<String, String> str = new HashMap<String, String>(); // String, String 타입 설정
    HashMap<Character, Character> ch = new HashMap<Character, Character>(); // Char, Char 타입 설정 
    	} 
    }

 먼저 Hashmap을 사용하기 위해서는, util에서 import 해줘야 합니다. 

그 후, Hashmap 생성 시 어떤 데이터를 저장할지 *Generics(String, Integer..)를 이용해 지정해줘야 합니다.

 또한 HashMap은 저장공간보다 값이 추가로 들어오면 List처럼 저장공간을 추가로 늘리는데, List처럼 저장공간을 한 칸씩 늘리지 않고 약 두배로 늘립니다. 여기서 과부하가 많이 발생하기 때문에 초기에 저장할 데이터 개수를 알고 있다면 Map의 초기 용량을 지정해주는 것이 좋습니다. ( new HashMap<>(용량 지정); )

 

*Generics : 데이터 형식에 의존하지 않고 클래스 내부에서 지정하는 것이 아닌 외부에서 사용자에 의해 지정되는 것

 


2.  Hashmap 값 추가

import java.util.HashMap; 

public class Test { 
	public static void main(String[] args) { 
    	HashMap<String, String> i1 = new HashMap<String, String>(); // HashMap 선언 
        
        // 값 추가 
        i1.put("1", "Hello1"); 
        i1.put("2", "World2"); 
        i1.put("3", "Hello3"); 
        i1.put("4", "World4"); 
        i1.put("2", "WorldWorld2"); 
        
        System.out.print(i1); // 결과 출력 
        } 
 }

  Hashmap에서 값을 추가할 때는 put() 메서드를 이용합니다. 이 때 키와 값의 타입 입력시에는Hashmap 생성 시에 명시한 Generics 타입으로 입력해줘야 합니다.( <String, String> )

 

 출력해보면 다음과 같습니다.

 위에서 Value는 고유한 속성이 아니기 때문에 중복이 가능하다고 했습니다. 그래서 2라는 key에는 마지막에 입력한 WorldWorld2가 덮어쓰여서 Hashmap에 저장됩니다.

 


3.  Hashmap 값 읽기

3.1 get()

import java.util.HashMap; 

public class Test { 
	public static void main(String[] args) { 
    	HashMap<String, String> i1 = new HashMap<String, String>(); // HashMap 선언 
        
        // 값 추가 
        i1.put("1", "Hello1"); 
        i1.put("2", "World2"); 
        i1.put("3", "Hello3"); 
        i1.put("4", "World4"); 
        i1.put("2", "WorldWorld2"); 
        
        System.out.print(i1); 
        System.out.print(i1.get("2"));
       
        } 
 }

 Hashmap 안의 데이터에 접근하는 법은 여러가지가 있습니다. 

먼저 그냥 print하게 되면 {}로 묶어 Map의 전체 key값, value가 출력됩니다. ( print(i1) )

 특정 key값의 value를 가져오고싶다면 get.()라는 메서드를 사용하면 됩니다. ( print(i1.get(key) ) 

 

3.2 keySet(), entrySet()

import java.util.HashMap;
import java.util.Map;

public class test {
    public static void main(String[] args) {
        HashMap<String, String> i1 = new HashMap<String, String>(); // HashMap 선언

        Map<String,Integer> i2=new HashMap();
        i2.put("key1",50);
        i2.put("key2",100);
        i2.put("key3",150);
        i2.put("key4",200);

        System.out.println("All key-value pairs");
        for(String key:i2.keySet()) {
            System.out.println("{"+key+","+i2.get(key)+"}");
        }

    }
}

 

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public class test {
    public static void main(String[] args) {
        HashMap<String, String> i1 = new HashMap<String, String>(); // HashMap 선언

        Map<String,Integer> i2=new HashMap();
        i2.put("key1",50);
        i2.put("key2",100);
        i2.put("key3",150);
        i2.put("key4",200);

        System.out.println("All key-value pairs");

        for (Entry<String, Integer> entry : i2.entrySet()) {
            System.out.println("[Key]:" + entry.getKey() + " [Value]:" + entry.getValue());
        }
    }
}

 

 전체를 출력(모든 Key 순회)하려면 entrySet()이나 keySet() 메서드를 활용하여 Map의 객체를 반환받은 후 출력하면 됩니다.

entrySet()은 key와 value 모두가 필요할 경우 사용하며, keySet()은 key 값만 필요할 경우 사용하는데 key값만 받아서 get(key)를 활용하여 value도 출력할 수도 있기에 어떤 메서드를 선택하든지 간에 큰 상관이 없어 대부분 코드가 간단한 keySet을 활용하지만, key값을 이용해서 value를 찾는 과정에서 시간이 많이 소모되므로 많은 양의 데이터를 가져와야 한다면 entrySet()이 좋습니다.


4.  Iterator 

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Iterator;

public class test {
    public static void main(String[] args) {
        HashMap<Integer, String> map = new HashMap<Integer, String>() {{
            put(1, "apple");
            put(2, "banana");
            put(3, "carrot");
        }};

        //entrySet().iterator()
        Iterator<Entry<Integer, String>> entries = map.entrySet().iterator();
        while (entries.hasNext()) {
            Map.Entry<Integer, String> entry = entries.next();
            System.out.println("[Key]:" + entry.getKey() + " [Value]:" + entry.getValue());
        }

        //keySet().iterator()
        Iterator<Integer> keys = map.keySet().iterator();
        while (keys.hasNext()) {
            int key = keys.next();
            System.out.println("[Key]:" + key + " [Value]:" + map.get(key));
        }
    }
}

 

 

 Hash와는 관계없지만 Hash와 함께 자주 쓰이는 Iterator입니다. Iterator는 List와 같은 컬렉션에서 요소들을 순차적으로 처리한 반복자입니다. 3번과 같이 반복분을 통해 출력할 수 있지만, Iterator를 사용하기도 합니다.

 Iterator 는 자동으로 Index를 관리해주기 때문에, 사용에 편리함이 있을수 있으나 객체를 만들어 사용하기 때문에 느리다는 점을 고려하고 사용해야 합니다. 


5.   getOrDefault()

  getOrDefault()도 iterator와 같이 Hashmap에서 자주 사용하기 때문에 추가해봤습니다. 

 getOrDefault()는 찾는 키가 존재한다면 찾는 키의 값을 반환하고 없다면 기본 값을 반환하는 메서드입니다.

getOrDefault(Object key, V DefaultValue)

매개 변수 : 이 메서드는 두 개의 매개 변수를 허용합니다.

  • key : 값을 가져와야 하는 요소의 
  • defaultValue : 지정된 키로 매핑된 값이 없는 경우 반환되어야 하는 기본값

반환 값 : 찾는 key가 존재하면 해당 key에 mapping되어 있는 값을 반환하고, 그렇지 않으면 디폴트 값이 반환됩니다.

 

import java.util.HashMap;

public class test {
    public static void main(String[] args) {
        String [] alphabet = { "A", "B", "C" ,"A"};
        HashMap<String, Integer> map = new HashMap<>();
        for(String key : alphabet) map.put(key, map.getOrDefault(key, 0) + 1);
        System.out.println("result : " + map);
    }
}

 Hashmap에서 value는 중복이 되기 때문에, A=2라는 결과를 볼 수 있었습니다.

'Studying > 자료구조' 카테고리의 다른 글

Java - DFS 구현  (0) 2022.06.28
Deque vs list 속도 차이  (0) 2022.05.01
Tree 구조  (0) 2022.04.30
Stack & Queue  (0) 2022.04.28
시간 복잡도  (0) 2022.04.20