티스토리 뷰

반응형

 

다음의 포스팅을 꼭 같이 읽어볼 것을 적극 권장한다.

(링크1)

(링크2)

 

 

이름 특징
Iterator 컬렉션에 저장된 요소를 접근하는데 사용되는 인터페이스
ListIterator Iterator에 양방향 조회기능 추가(List를 구현한 경우만 사용가능)
Enumeration Iterator 구버전

 

 

다음과 같이 컬렉션 클래스에 대해 iterator()를 호출하여 Iterator를 얻은다음

반복문, 주로 while문을 사용해서 컬렉션 클래스의 요소들을 읽어온다.

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class P413 {
    public static void main(String[] args) {
        List list = new ArrayList(); // 다른 컬렉션으로 변경할 때는 이 부분만 변경하면 됨. (재사용성)
        Iterator it = list.iterator();
        
        while(it.hasNext()) { // boolean hasNex()로 읽어올 요소가 있는지 확인
            System.out.println(it.next()); // Object next() 다음 요소를 읽어옴.
        }
        
    }
}

 

 

🧡 배열의 복사 - copyOf(), copyOfRange()

💛 배열 채우기 - fill(), setAll()

fill() : 배열의 모든 요소 지정된 값으로 채움.

setAll() : 배열을 채우는데 사용할 함수형 인터페이스를 매개변수로 받음.

💚 배열의 정렬과 검색 - sort(), binarySearch()

💙 문자열의 비교와 출력 - equals(), toString()

toString() : 배열의 모든 요소 문자열로 출력

equals() : 두 배열에 저장된 모든 요소를 비교해서 같으면 true, 다르면 false 반환

 

👉 다음의 결과를 살펴보자. 

import java.util.Arrays;

public class P416 {
    public static void main(String[] args) {
        String[][] str2D = new String[][]{{"aaa","bbb"}, {"AAA", "BBB"}};
        String[][] str2D2 = new String[][]{{"aaa","bbb"}, {"AAA", "BBB"}};

        System.out.println(Arrays.equals(str2D, str2D2)); // false
        System.out.println(Arrays.deepEquals(str2D, str2D2)); // true

        /*
        false 나오는 이유
        '배열의 값'이 아닌 '배열의 주소'를 저장하기 때문
        서로 다른 배열(객체)는 항상 주소가 다르므로 false 리턴!!
         */

    }
}

💜 배열을 List로 변환 - asList(Object..a)

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class P416 {
    public static void main(String[] args) {
        List list = Arrays.asList(new Integer[]{1,2,3,4,5}); // list = [1,2,3,4,5]
        List list2 = Arrays.asList(1,2,3,4,5);
        list2.add(6); // UnsupportedOperationException 예외 발생
        /*
        예외 발생 이유
        asList()가 반환한 List의 크기를 변경할 수 업음.
        추가, 삭제 불가
        크기 변경이 불가하므로 저장된 값은 변경 가능
        크기 변경 가능한 List로 작성하고 싶으면 다음과 같이 하자.
        List list = new ArrayList(Arrays.asList(1,2,3,4,5));
         */
    }
}

 

 


 

 

 

🤔 Comparator와 Comparable ⭐⭐⭐

✔ 컬렉션을 정렬하는데 필요한 메서드 정의

✔ 객체 정렬에 필요한 메서드(정렬기준 제공)를 정의한 인터페이스

 

✅ Comparable : 기본 정렬기준을 구현하는데 사용

✅ Comparator : 기본 정렬 기준 외에 다른 기준으로 정렬할 때 사용

public interface Comparator {
	int compare(Object o1, Object o2); // o1, o2 두 객체 비교
    boolean equals(Object obj); // equals를 오버라이딩하라는 뜻
}

public interface Comparable {
	int compareTo(Object o); // 주어진 객체(o)를 자신과 비교
}

 

 

✔ compare()와 compareTo()는 두 객체의 비교 결과를 반환하도록 작성

public final class Integer extends Number implements Comparable {
	...
    public int compareTo(Integer anotherInteger) {
    	int v1 = this.value;
        int v2 = anotherInteger.value;
        // 같으면 0, 오른쪽 값이 크면 -1, 작으면 1 반환
        return (v1 < v2 ? -1 : (v1==v2? 0 : 1));
    }
    ...
}

 

 

 

이름 특징
Comparable 기본 정렬기준을 구현하는데 사용
Comparator 기본 정렬기준 외에 다른 기준으로 정렬하고자 할 때 사용

 

 

예제를 통해 개념을 학습하자.

import java.util.Arrays;
import java.util.Comparator;

public class Ex11_7 {
    public static void main(String[] args) {
        String[] strArr = {"cat", "Dog", "lion", "tiger"};

        Arrays.sort(strArr); // String의 Comparable 구현에 의한 정렬
        System.out.println("strArr = " + Arrays.toString(strArr));

        Arrays.sort(strArr, String.CASE_INSENSITIVE_ORDER); // 대소문자 구분 x
        System.out.println("strArr = " + Arrays.toString(strArr));

        Arrays.sort(strArr, new Descending()); // 역순 정렬
        System.out.println("strArr = " + Arrays.toString(strArr));
    }
}

class Descending implements Comparator {
    public int compare(Object o1, Object o2) {
        if(o1 instanceof Comparable && o2 instanceof Comparable){
            Comparable c1 = (Comparable)o1;
            Comparable c2 = (Comparable)o2;
            return c1.compareTo(c2) * -1; // -1 곱해서 기본 정렬방식 역순으로 변경
            // 또는 c2.compareTo(c1)으로 작성가능
        }
        return -1;
    }
}

 

import java.util.Arrays;
import java.util.Comparator;

public class Ex11_8 {
    public static void main(String[] args) {
        Integer[] arr = {30, 50, 10, 40, 20};

        Arrays.sort(arr); // Integer가 가지고 있는 기본 정렬 기준 compareTo()로 정렬
        System.out.println(Arrays.toString(arr));
        
        // sort(Object[] objArr, Comparator c)
        Arrays.sort(arr, new DescComp()); // DescCOmp에 구현된 정렬 기준으로 정렬
        System.out.println(Arrays.toString(arr));
    } // main
}

class DescComp implements Comparator {
    public int compare(Object o1, Object o2) {
        if(!(o1 instanceof Integer && o2 instanceof Integer)) 
            return -1; // Integer가 아니면, ㅂ교하지 말고 -1 반환
        
        Integer i = (Integer) o1;
        Integer i2 = (Integer) o2;
        // return i2 - i; 또는 return i2.compareTo(i);도 가능
        return i.compareTo(i2) * -1; // 기본 정렬인 compareTo()의 역순으로 진행
        
        
    }
}

 

 


 

 

🤔 HastSet -  순서 x, 중복 x

✔ Set 인터페이스를 구현한 대표적인 컬렉션 클래스

✔ 순서를 유지하려면, LinkedHashSet 사용해야 함.

 

🤔 HashSet - 순서 x, 중복 x

✔ 객체를 저장하기 전에 기존에 같은 객체가 있는지 확인

같은 객체가 없으면 저장하고, 있으면 저장하지 않는다.

✔ boolean add(Object o)는 저장할 객체의 equals()와 hashCode()를 호출

equals()와 hashCode()가 오버라이딩 되어 있어야 함(hashCode()는 필수 아님, 권유)

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Ex11_9 {
    public static void main(String[] args) {
        Object[] objArr = {"1", new Integer(1), "2", "3", "3", "4", "4", "4"};
        Set set = new HashSet();
        
        for(int i=0; i<objArr.length; i++) {
            set.add(objArr[i]); // HashSet에 objArr의 요소들을 저장
        }
        // HashSet에 저장된 요소 출력
        System.out.println(set);
        
        // HastSet에 저장된 요소 출력(Iterator이용)
        Iterator it = set.iterator();
        while(it.hasNext()) { // 얻어올 요소 있는지 확인
            System.out.println(it.next()); // 요소 하나 꺼내오기
        }
    }
}
import java.util.*;

public class Ex11_10 {
    public static void main(String[] args) {
        Set set = new HashSet();

        for(int i=0; set.size()<6; i++) {
            int num = (int) (Math.random()*45) + 1;
            set.add(new Integer(num));
        }
        List list = new LinkedList(set); // LinkedList(Collection c)
        Collections.sort(list); // Collections.sort(List list)
        System.out.println(list);
        // Collection : 인터페이스, Collections : 클래스
    }
}
import java.util.HashSet;
import java.util.Objects;

public class Ex11_11 {
    public static void main(String[] args) {
        HashSet set = new HashSet();
        set.add("abc");
        set.add("abc");
        set.add(new Person("David", 10));
        set.add(new Person("David", 10));
        System.out.println(set);
    }
}

class Person {
    String name;
    int age;
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String toString() { return name + ":" + age; }

    public boolean equals(Object obj) {
        if(!(obj instanceof Person)) return false;
        Person p = (Person) obj;
        return name.equals(p.name) && age==p.age;
    }

    public int hashCode() {
        return Objects.hash(name, age); // int hash(Object... values)
    }
}

 

equals(), hashCode() 없으면 두 인스턴스의 name과 age 같아도 서로 다른 것으로 인식함.

 

 

import java.util.HashSet;
import java.util.Iterator;

public class Ex11_12 {
    public static void main(String[] args) {
        HashSet setA = new HashSet();
        HashSet setB = new HashSet();
        HashSet setHab = new HashSet();
        HashSet setKyo = new HashSet();
        HashSet setCha = new HashSet();

        setA.add("1");
        setA.add("2");
        setA.add("3");
        setA.add("4");
        setA.add("5");
        System.out.println("A = " + setA);

        setB.add("4");
        setB.add("5");
        setB.add("6");
        setB.add("7");
        setB.add("8");
        System.out.println("A = " + setB);

        Iterator it = setB.iterator();
        while (it.hasNext()) {
            Object tmp = it.next();
            if (setA.contains(tmp)) {
                setKyo.add(tmp);
            }
        }
        it = setA.iterator();
        while (it.hasNext()) {
            Object tmp = it.next();
            if (!setB.contains(tmp)) {
                setCha.add(tmp);
            }
        }

        it = setA.iterator();
        while(it.hasNext()) {
            setHab.add(it.next());
        }

        it = setB.iterator();
        while(it.hasNext()) {
            setHab.add(it.next());
        }

        System.out.println("A ∩ B = " + setKyo);
        System.out.println("A ∪ B = " + setHab);
        System.out.println("A - B = " + setCha);
    }
}

 

다음과 같이 합집합, 차집합, 교집합을 구할 수도 있다.👇👇

setA.retainAll(setB); // 교집합. 공통된 요소만 남기고 삭제
setA.addAll(setB); // 합집합. setB의 모든 요소를 추가(중복 제외)
setA.removeAll(setB); // 차집합. setB와 공통 요소를 제거

 

 


🤔 TreeSet - 범위 탐색, 정렬

✔  이진 탐식 트리(binary search tree)로 구현, 범위 탐색과 정렬에 유리

✔ 이진 트리는 모든 노드가 최대 2개의 하위 노드 가짐.

각 요소(node)가 나무(tree)형태로 연결(LinkedList의 변형)

 

class TreeNode {
    TreeNode left; // 왼쪽 자식노드
    Object element; // 객체를 저장하기 위한 참조변수
    TreeNode right; // 오른쪽 자식노드
}

 

 

🤔 이진 탐색 트리(binary search tree)

✔ 부모보다 작은 값 왼쪽, 큰 값 오른쪽에 저장

✔ 단점 : 데이터 많아질수록 추가,삭제 시간 오래걸림(비교 횟수 증가)

 

예제를 통해 살펴보자. 👇👇

import java.util.Set;
import java.util.TreeSet;

public class Ex11_13 {
    public static void main(String[] args) {
        Set set = new TreeSet();

        for(int i=0; set.size()<6; i++) {
            int num = (int)(Math.random()*45)+1;
            set.add(num);
        }
        System.out.println(set);
        // TreeSet은 저장할 때 이미 정렬하기 때문에 읽어올 때 바로 정렬할 필요 없어서
        // Collections.sort(list); 이런식으로 정렬 안해도됨.
    }
}

 

 

import java.util.TreeSet;

public class Ex11_14 {
    public static void main(String[] args) {
        TreeSet set = new TreeSet();

        String from = "b";
        String to = "d";

        set.add("abc");
        set.add("alien");
        set.add("bat");
        set.add("car");
        set.add("Car");
        set.add("disc");
        set.add("dance");
        set.add("dZZZZ");
        set.add("dzzzz");
        set.add("elephant");
        set.add("elevator");
        set.add("fan");
        set.add("flower");

        System.out.println(set);
        System.out.println("range search : from " + from + " to " + to);
        System.out.println("result1 : " + set.subSet(from, to));
        System.out.println("result2 : " + set.subSet(from, to + "zzz")); 
    }
}

 

import java.util.TreeSet;

public class Ex11_15 {
    public static void main(String[] args) {
        TreeSet set = new TreeSet();
        int[] score = {80, 95, 50, 35, 45, 65, 10, 100};
        
        for(int i=0; i<score.length; i++) {
            set.add(new Integer(score[i])); // set.add(score[i]);도 가능
        }
        System.out.println("50보다 작은 값 : " + set.headSet(new Integer(50)));
        System.out.println("50보다 큰 값 : " + set.tailSet(new Integer(50)));
    }
}

 

 

🤔 트리 순회(tree traversal)

✔ 이진 트리의 모든 노드를 한 번씩 읽는 것

✔ 전위, 중위, 후위 순회법이 있으며, 중위 순회하면 오름차순으로 정렬된다.

 

 


🤔 HashMap과 Hashtable - 순서x, 중복(키x, 값o)

✔ Map 인터페이스를 구현, 데이터를 키와 값의 쌍으로 저장

HashMap(동기화x)은 hashtable(동기화o)의 신버전

 

🤔 HashMap

✔ Map 인터페이스를 구현한 대표적인 컬렉션 클래스

순서를 유지하려면, LinkedHashMap 클래스 사용

 ✔ 해싱(hashing) 기법으로 데이터를 저장, 데이터가 많아도 검색 빠름.

✔ Map 인터페이스 구현, 데이터를 키와 값의 쌍으로 저장

종류 기능
키(key) - 중복 x 컬렉션 내의 키(key) 중에서 유일해야 함.
값(value) - 중복 o 키(key)와 달리 데이터의 중복 허용

 

비객체지향적인 코드 객체지향적인 코드
Object[] key;
Object[] value;
Entry[] table;

class Entry {
    Object key;
    Object value;
}

 

🤔 TreeMap

✔ 범위 검색과 정렬에 유리한 컬렉션 클래스

✔ HashMap보다 데이터 추가, 삭제데 시간이 더 걸림

 

💡 해싱(hashing)이란?

✔ 해시함수(hash function)로 해시테이블(hash table)에 데이터를 저장, 검색

✔ 해시테이블은 배열과 링크드 리스트가 조합된 형태

✔ 해시테이블에 저장된 데이터를 가져오는 과정

1. 키로 해시함수를 호출해서 해시코드를 얻는다.

2. 해시코드(해시함수의 반환값)에 대응하는 링크드리스트를 배열에서 찾는다.

3. 링크드리스트에서 키와 일치하는 데이터를 찾는다.

🧡 해시함수는 같은 키에 대해 항상 같은 해시코드를 반환해야 한다.

서로 다른 키일지라도 같은 값의 해시코드를 반환할 수도 있다.

 

 

예시를 통해 제대로 이해하자. 👇👇

import java.util.HashMap;
import java.util.Scanner;

public class Ex11_16 {
    public static void main(String[] args) {
        HashMap map = new HashMap();
        map.put("myId", "1234");
        map.put("asdf", "1111");
        map.put("asdf", "1234"); // OK. 이미 존재하는 키 추가가능, 기존 값은 없어짐

        Scanner sc = new Scanner(System.in); // 화면으로부터 라인단위로 받는다.
        while(true) {
            System.out.println("id와 password를 입력해주세요.");
            System.out.println("id : ");
            String id = sc.nextLine().trim();

            System.out.println("password :");
            String password = sc.nextLine().trim();
            System.out.println();

            if(!map.containsKey(id)) {
                System.out.println("입력하신 id는 존재하지 않습니다. 다시 입력해주세요.");
                continue;
            }

            if(!(map.get(id)).equals(password)) {
                System.out.println("비밀번호가 일치하지 않습니다. 다시 입력해주세요.");
            } else {
                System.out.println("id와 비밀번호가 일치합니다.");
                break;
            }
        } // while
    } // main
}

 

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

public class Ex11_18 {
    public static void main(String[] args) {
        String[] data = {"A", "K", "A", "K", "D", "K", "A", "K", "K", "K", "Z", "D"};

        HashMap map = new HashMap();

        for(int i=0; i<data.length; i++) {
            if(map.containsKey(data[i])) {
                int value = (int)map.get(data[i]);
                map.put(data[i], value + 1);
            }else {
                map.put(data[i], 1);
            }
        }

        Iterator it = map.entrySet().iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            int value = (int)entry.getValue();
            System.out.println(entry.getKey() + " : " + printBar('#', value) + " " + value);
        }
    }// main

    public static String printBar(char ch, int value) {
        char[] bar = new char[value];

        for(int i=0; i<bar.length; i++) {
            bar[i] = ch;
        }
        return new String(bar); // String(char[] chArr) 
    }
}

 

 

이상으로 자바의 정석 Ch11 공부를 마친다.

 

반응형