Java의 정석_기초편

Iterator<E>, HashMap<K,V>

DJDU 2022. 11. 7. 19:22

Iterator<E>

  • 클래스를 작성할 때, Object타입 대신 T와 같은 타입 변수를 사용
더보기

Iterator<E>

일반 클래스 ➝ 지네릭 클래스
타입변수 E ➝ Student 타입 대입

예제12-2

더보기

코드

package ch12;

import java.util.*;

class Ex12_2 {
    public static void main(String[] args) {
        ArrayList<Student> list = new ArrayList<Student>();
        list.add(new Student("자바왕", 1, 1));
        list.add(new Student("자바짱", 1, 2));
        list.add(new Student("홍길동", 2, 1));

        Iterator<Student> it = list.iterator();
//      Iterator it = list.iterator();
        while (it.hasNext()) {
//          Student s = it.next();
//          Student s = (Student)it.next(); // 지네릭스를 사용하지 않으면 형변환 필요.
//          System.out.println(s.name);
//          System.out.println(((Student)it.next()).name);
            System.out.println(it.next().name);
        }
    } // main
}

class Student {
    String name = "";
    int ban;  // 반
    int no;   // 번호

    Student(String name, int ban, int no) {
        this.name = name;
        this.ban = ban;
        this.no = no;
    }
}

Iterator 호출 시 '대입된 타입'을 명시하지 않는다면 어떻게 될까?

//  Iterator<Student> it = list.iterator();
    Iterator it = list.iterator();

요소 '읽어오기' 시, 형 변환을 해주어야 한다.

Iterator it = list.iterator();
while (it.hasNext()) {
    Student s = (Student)it.next(); // 지네릭스를 사용하지 않으면 형변환 필요.
    System.out.println(s.name);
//  System.out.println(((Student)it.next()).name);
}  // 물론 형변환 필요 시에도, 한 줄로 작성할 수 있지만 코드가 복잡해진다.

Iterator 호출 시 '대입된 타입'을 명시하여 형 변환이 필요 없다면 다음과 같이 작성해주면 된다.

Iterator<Student> it = list.iterator();
while (it.hasNext()) {
    Student s = it.next();  // 형 변환 불필요 - next()의 반환타입이 Student이기 때문
    System.out.println(s.name);
}

while문 안의 두 줄을 한 줄로 표현 가능하다.

Iterator it = list.iterator();
while (it.hasNext()) {
    System.out.println(it.next().name);  // 위 두 줄 코드를 한 줄로 표현가능
}  //

단순히 형 변환만 생략했을 뿐인데, 코드가 이렇게 간단해진다. 물론 형 변환을 생략하지 않아도 코드를 한 줄로 표현할 수는 있지만 코드가 복잡해진다.

HashMap<K,V>

  • 여러 개의 타입 변수가 필요한 경우, 콤마(,)를 구분자로 선언
더보기

여러 개의 타입 변수가 필요한 경우, 콤마(,)를 구분자로 선언

HashMap<String, Student> map = new HashMap<String, Student>();  // 생성

HashMap<String, Student>에서 원래 두 타입 변수는 모두 Object 타입이었다. 그런데, 두 타입이 항상 같지 않다. 다를 수 있기 때문에 Key = String, Value = Student일 수 있다. (K는 Key, V는 Value에서 가져온 것이다. 꼭 명칭이 고정된 건 아니다)

그래서 HashMap을 저장할 때 HashMap<String, Student>란 HashMap의 Key가 String타입, Value가 Student타입이라는 의미이다.

당연히, 참조변수의 타입 변수 Key-Value와 생성자의 타입 변수 Key-Value는 일치해야 한다.

map.put("자바왕", new Student("자바왕", 1, 1, 100, 100, 100));     // 데이터 저장

HashMap에 대해 put메서드를 호출하는 코드이다. 첫 번째는 Key로 String타입의 "자바왕"이 삽입됐고, 두 번째 인자는 Value로 Student 타입의 새로운 객체가 삽입되었다.

지정된 대로 타입이 일치하지 않으면 '컴파일 에러'가 발생한다.

public class HashMap<K,V> extends AbstractMap<K,V> {  // 일부 생략
        ...
    public V get(Object key)     { /* 내용 생략 */ }
    public V pub(K key, V value) { /* 내용 생략 */ }
    public V remove(Object key)  { /* 내용 생략 */ }
        ...
}

HashMap을 까보면 위와 같이 나와 있다.

public class HashMap extends AbstractMap { // 일부 생략
        ...
    public Student get(Object key)                   { /* 내용 생략 */ }
    public Student put(String key, Student value)    { /* 내용 생략 */ }
    public Student remove(Object key)                { /* 내용 생략 */ }
        ...
}
지네릭스를 사용하면 형 변환하지 않아도 된다.

저번 시간에 배운 내용과 비교해보자.

예제12-2-2

더보기

코드

package ch12;

import java.util.HashMap;

class Ex12_2_2 {
    public static void main(String[] args) {
//      HashMap map = new HashMap();
        HashMap<String, Student2> map = new HashMap<>();  // JDK1.7부터 생성자에 타입지정 생략가능
        map.put("자바왕", new Student2("자바왕", 1, 1, 100, 100, 100));

//      Student2 s = (Student)map.get("자바왕");
        Student2 s = map.get("자바왕");  // public Student get(Object key) {

        System.out.println(map);
        System.out.println(map.get("자바왕").name);
    } // main
}

class Student2 {
    String name = "";
    int ban;  // 반
    int no;   // 번호
    int kor;
    int eng;
    int math;

    Student2(String name, int ban, int no, int kor, int eng, int math) {
        this.name = name;
        this.ban = ban;
        this.no = no;
        this.kor = kor;
        this.eng = eng;
        this.math = math;
    }
}