[Java] 자바 #31, 컬렉션 프레임워크 - HashMap

ArrayList와 HashMap의 비교


1. ArrayList 

- 요소에 대한 접근 : index사용 

- 요소에 순서가 존재 

- 첨자 : 정수사용.(0부터 시작, Zero-based Index) 

- 스칼라 배열(Scalar Array) (HashMap과의 비교) : 방들을 일괄 접근하기 용이(***)

- for문 : 요소간의 구분이 쉽지 않다.(3번째 방? 27번째 방?)


2. HashMap 

- 요소 접근 -> 키(key)사용 

- 키 : 숫자, 문자, 문자열(***이것만쓴다거의***) 등... 

- 방번호(인덱스) X,

- 요소에 순서도 없음. -연관 배열, 사전구조 -Key, Value (ArrayList와의 비교) : 일괄 접근이 불리(거의 사용 안함)

- for문과 잘 연동 안함

- 요소 하나하나를 직접 접근 : 요소간의 구분이 아주 쉽다.(사용자가 정의한 식별자를 이용) > 의미가 있게 짓는 것이 가능 

- 키가 반드시 유일해야한다. (중복된 키를 가질 수 없다.)


HashMap의 기능


0. 객체생성

- raw Type : 레거시

HashMap map = new HashMap();


- 제네릭을 사용 : <키, 값>으로 제네릭의 타입을 선언

HashMap<String, Integer> map = new HashMap<String, Integer>();


1. 요소 쓰기(Create)

map.put("국어", 100);

map.put("영어", 90);

map.put("수학", 80);

map.put("국어", 70);


2. 요소 읽기(R)

System.out.println(map.get("국어"));


주의for문이랑 쓰려고 하지 말자.

HashMap<Integer, String> map2 = new HashMap<Integer, String>();

map2.put(1, "하나");

map2.put(2, "둘");

map2.put(3, "셋");

System.out.printf("%s\t", map2.get(2));

>> 이런식으로 쓸거면 그냥 ArrayList 쓰는게 낫다.


boolean값으로 를? => 키가 2개밖에 없는데 쓰는 범위가 너무 좁아진다.

HashMap<Boolean, String> map3 = new HashMap<Boolean, String>();

map3.put(true, "참");

map3.put(false, "거짓");

System.out.println(map3.get(false));


boolean값으로 을? => 해당 상황에 따라 HashMap이 효율적인지 판단하고 쓰는게 좋을 것 같습니다.

HashMap<String, Boolean> map4 = new HashMap<String, Boolean>();

map4.put("홍길동", true);

map4.put("아무개", false);

map4.put("멍멍이", true);

map4.put("김부각", true);


if (map4.get("멍멍이")) {

System.out.println("합격");

} else {

System.out.println("불합격");

}


3. map의 크기(들어간 요소의 개수)

- int size()

ex) 성적데이터 넣기

HashMap<String, Double> score = new HashMap<String, Double>();

score.put("국어", 100.0);

score.put("영어", 85.5);

score.put("수학", 73.2);

score.put("사회", 60.0);

score.put("국사", 90.5);

System.out.println(score.size());  5


4. 요소접근

System.out.println(score.get("국사"));


5. 요소수정 (= 입력 ) 덮어쓰기형태

System.out.printf("국어 : %s\n", score.get("국어"));

score.put("국어", 95.0); 국어라는 키는 이미 있으므로 해당 키에다가 다른 값을 넣어주면 그게 수정이됨.

System.out.printf("국어 : %s\n", score.get("국어"));


6. 삭제

score.remove("국사");

System.out.println(score.size());

System.out.println(score.get("국사"));// null

// 스칼라 배열은 없는 방번호에 접근할 때 예외, 연관배열은 null을 반환.


7. 검색

- String , Array, ArrayList -> indexOf, contains

- HashMap -> contains

ex)

System.out.println(score.containsKey("국사")); // 참, 거짓반환 키값으로 접근.

System.out.println(score.containsValue(95.0));// 참, 거짓 반환 Value값으로 접근.


8. 초기화

score.clear(); HashMap<String,Integer> score = new HashMap<String,Integer>(); 상태로 다시 돌아간다고 생각.

System.out.println(score.size());


임의로 구현한 HashMap 예제


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
class MyHashMap {
 
    private int index;
    private String[] key;
    private String[] value;
 
    public MyHashMap() {
        this.index = -1;
        this.key = new String[100];
        this.value = new String[100];
    }
    
    private int getIndex(String key) {
        for (int i = 0; i <= this.index; i++) {
            if(this.key[i].equals(key)) {
                return i;
            }
        }
        return -1;
    }
    
    public void put(String key, String value) { // 수정, 대입.
        //여기서 이미 있는 키값일때는 index를 증가시키지 않는다.
        if(getIndex(key)>-1) { // 동일한 키값이 존재할 경우.
            this.value[getIndex(key)]=value;
            return// 메소드 종료용...
        }
        //대입.
        this.index++;
        this.key[this.index] = key;
        this.value[this.index]= value;
    }
    
    public String get(String key) {
        if(this.getIndex(key)>-1) { // 인덱스가 존재하는
            return value[getIndex(key)];//value와 key의 인덱스는 대응하므로 
        }
        return null;
    }
    public int size() {
        return this.index+1;
    }
    
    public void remove(String key) {
        int removeIndex=this.getIndex(key); // 해당 키값이 존재하는 인덱스를 저장.
        
        //해당 키값이 없으면 그대로 종료.
        if(removeIndex==-1) {
            return;
        }
        
        //있으면 이쪽으로 흘러서.
        for(int i=removeIndex; i<this.index;i++) {
            //제거작업. 위에서 아래로 덮어쓰기가 되어야 하므로
            this.key[i]=this.key[i+1];
            this.value[i]=this.value[i+1];
        }
        this.key[this.index]=null;
        this.value[this.index]=null;
        this.index--;
        
    }
    
    public boolean containKey(String key) {
        if(getIndex(key)>-1) { // 겟 인덱스를 통해서 key값 존재.
            return true;
        }
        return false;
    }
    
    public boolean containValue(String value) {
        
        for(int i =0; i<=this.index;i++) { // 처음부터 인덱스까지 돌아서 
            if(this.value[i].equals(value)) { // 같은 값이 존재한다면.
                return true;
            }
        }
        return false;
    }
    
    public void clear() {
        this.key = new String[100];
        this.value=new String[100];
        this.index=-1;
    }
}
cs


설명

해쉬맵도 사실 배열로 구현되어있는데, 길이를 임의로 100으로만 고정해놨는데, 원래는 4부터 시작해서 배수로 4, 8, 16, 32 ... 이렇게 늘어나야 합니다. 

그리고 getIndex(String key)라는 내부메소드를 통해 key배열에 있는 값에 매칭되는 value 배열의 인덱스 값을 반환하는 메소드를 활용해서 다른 메소드를 구현하는데 용이하게 사용하였습니다.








댓글

Designed by JB FACTORY