JAVA January 04, 2021

java-02 Map

Words count 7.7k Reading time 7 mins.

JSP 에서 Map 의 사용이 중요하기 때문에 먼저 정리해 보았습니다.

맵 (Map)

‘사람’을 예로 들면 누구든지 “이름” = “홍길동”, “생일” = “몇 월 몇 일” 등으로 구분할 수 있다. 자바의 맵(Map)은 이러한 대응관계를 쉽게 표현할 수 있게 해 주는 자료형이다. 이것은 요즘 나오는 대부분의 언어들도 갖고 있는 자료형으로 Associative array, Hash라고도 불린다.

맵(Map)은 사전(dictionary)과 비슷하다. 즉, people 이란 단어에 “사람”, baseball 이라는 단어에 “야구”라는 뜻이 부합되듯이 Map은 Key와 Value라는 것을 한 쌍으로 갖는 자료형이다.

key value
people 사람
baseball 야구

Map은 리스트나 배열처럼 순차적으로(sequential) 해당 요소 값을 구하지 않고 key를 통해 value를 얻는다. 맵(Map)의 가장 큰 특징이라면 key로 value를 얻어낸다는 점이다. baseball이란 단어의 뜻을 찾기 위해서 사전의 내용을 순차적으로 모두 검색하는 것이 아니라 baseball이라는 단어가 있는 곳만을 펼쳐보는 것이다.

put

자바의 맵(Map)중 가장 간단한 HashMap에 대해서 알아보자.

Map 역시 List와 마찬가지로 인터페이스이다.

HashMap<String, String> map = new HashMap<String, String>();
map.put("people", "사람");
map.put("baseball", "야구");

key와 value가 String 형태인 HashMap을 만들고 위에서 보았던 예제의 항목값들을 입력해 보았다. key와 value는 위 예제에서 보듯이 put메소드를 이용하여 입력한다.

※ HashMap 역시 제네릭스를 이용한다. 위의 HashMap 의 제네릭스는 Key, Value 모두 String 타입이다.

get

key에 해당되는 값을 얻기 위해서는 다음과 같이 한다.

System.out.println(map.get("people"));

위와같이 get 메소드를 이용하면 value값을 얻을 수 있다. 위 예제는 결과로 “사람”이라는 문자열을 출력할 것이다.

containsKey

containsKey 메소드는 맵(Map)에 해당 키(key)가 있는지를 조사하여 그 결과값을 리턴한다.

System.out.println(map.containsKey("people"));

“people”이라는 키는 존재하므로 true가 출력될 것이다.

remove

remove 메소드는 맵(Map)의 항목을 삭제하는 메소드로 key값에 해당되는 아이템(key, value)을 삭제한 후 그 value 값을 리턴한다.

System.out.println(map.remove("people"));

“people”에 해당되는 아이템(people:사람)이 삭제된 후 “사람”이 출력될 것이다.

다음은 테스트 시 사용되었던 코드 전체이다.

TestMap.java

import java.util.HashMap;

public class TestMap {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("people", "사람");
map.put("baseball", "야구");

        System.out.println(map.get("people"));
        System.out.println(map.containsKey("people"));
        System.out.println(map.remove("people"));
        System.out.println(map.size());
    }
}

LinkedHashMap과 TreeMap

Map의 가장 큰 특징은 순서에 의존하지 않고 key로 value를 가져오는데 있다. 하지만 가끔은 Map에 입력된 순서대로 데이터를 가져오고 싶은 경우도 있고 때로는 입력된 key에 의해 소트된 데이터를 가져오고 싶을 수도 있을 것이다. 이런경우에는 LinkedHashMap과 TreeMap을 사용하는 것이 유리하다.

  • LinkedHashMap은 입력된 순서대로 데이터가 출력되는 특징을 가지고 있다.
  • TreeMap은 입력된 key의 소트순으로 데이터가 출력되는 특징을 가지고 있다.

Ex02-HashMap

public class Ex02_HashMap {

    public static void main(String[] args) {

        // 어떤 사람의 정보(이름, 나이, 키, 성별)를 Map으로 생성
        Map<String, String> person = new HashMap<>();

        person.put("name", "alice");
        person.put("age", 20 + "");
        person.put("height", 175.5 + "");
        person.put("gender", "여");

        // 순회 1. keySet() 메소드
        // 1. key만 뺀다.
        // 2. key들은 Set에 저장해야만 한다.
        // 3. get() 메소드에 Set에서 뺀 key를 전달하면 value가 나온다.

        // 1) Iterator
        Set<String> set = person.keySet(); // set = ["name", "age", "height", "gender"]

        Iterator<String> itr = set.iterator();

        while (itr.hasNext()) {
            String key = itr.next(); // itr.next() == key : "name" -> "age" -> "height" -> "gender"(임의의 순서)
            String value = person.get(key); // person.get("name") ==> "alice"
            System.out.println(key + " : " + value);
        }

        // 2) 향상 for문
        for (String key : person.keySet()) {
            String value = person.get(key);
            System.out.println(key + " : " + value);
        }

        // 순회 2. entrySet() 메소드
        // entry : key와 value를 묶어서 부르는 말(person은 entry가 4개 있다.)
        // key : getKey() 메소드
        // value : getValue() 메소드

        // 1) 향상 for문

        for (Map.Entry<String, String> entry : person.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + " : " + value);
        }

        // 2) Iterator
        Set<Map.Entry<String, String>> set2 = person.entrySet();
        Iterator<Map.Entry<String, String>> itr2 = set2.iterator();

        while (itr2.hasNext()) {
            Map.Entry<String, String> entry = (Map.Entry<String, String>) itr2.next();
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + " : " + value);
        }

    }

}

Ex02_HashSet

class Member {

    private String id;

    public Member(String id) {
        super();
        this.id = id;
    }

    // hashCode() 메소드를 만들면 Object 클래스의 hashCode() 메소드 사용되지 않는다.
    @Override
    public int hashCode() {

        // return 1; // 임의 설정 -> 모든 Member는 hash값이 1이므로 같은 Member일 가능성이 있다고 판단한다. (최악의 hashCode)
        // return id.length();    // id의 글자수가 같은 Member일 가능성이 있다고 판단한다.
        return id.charAt(0);    // id의 첫 번째 글자가 같으면, 같은 Member일 가능성이 있다고 판단한다.  >>> 그룹이 세밀해질수록 더 좋다
    }

    // hashCode() 결과가 같으면 equals() 메소드를 호출해서 비교한다.
    // equals() 메소드를 만들면 Object 클래스의 equals() 메소드는 사용되지 않는다.
    @Override
    public boolean equals(Object obj) {    // m1.equals(m2)
        // this.id = m1     obj = m2 (다운캐스팅 필요)
        return id.equals(((Member)obj).id);
    }

    // hashCode 와 equals 자동생성 기능이 있다. hashCode() 의 계산법은 자동 생성이 더 뛰어나기 때문에 자동 생성 사용할 것 

}

public class Ex02_HashSet {

    public static void main(String[] args) {

        // HashSet 클래스는 중복 저장이 불가능하다.
        // 중복 체크 방법
        // 1단계. hashCode 값을 비교한다.(같은 hashCode이면 같은 객체일 가능성이 있다.
        // 2단계. equals로 비교한다.

        Member m1 = new Member("abc");
        Member m2 = new Member("abc");
        Member m3 = new Member("xyz");

        Set<Member> set = new HashSet<>();

        set.add(m1);
        set.add(m2);

        System.out.println(set);

        // HashMap의 활용
        // 회원(Member)별 포인트(Integer) 관리

        Map<Member, Integer> map = new HashMap<>();

        map.put(m1, 5000);    // m1 회원의 포인트 : 5000
        map.put(m1, 6000);    // m1 회원의 포인트 : 6000 으로 수정
        map.put(m3, 10000);    // m1 회원의 포인트 : 10000

        System.out.println(map); 
        }

}
0%