Enum / Generic / Collection

jungseo·2023년 5월 1일
0

Java

목록 보기
5/10

열거형(Enum)

여러 상수들을 편리하게 선언하고 관리할 수 있고 상수 명의 중복을 피하고 타입에 대한 안정성을 보장함

enum 열거형 이름 { 상수명1, 상수명2, ... }
enum Seasons {SPRING, SUMMER, FALL, WINTER}
  • Seasons라는 이름의 열거형이 4개의 열거 객체를 포함
  • publuc static final으로 정의 했을때와 다르게 switch문에 사용 가능
import java.util.Arrays;

enum Seasons {SPRING, SUMMER, FALL, WINTER}

public class EnumTest {
    public static void main(String[] args) {
        
        // name() 열거 객체가 가지고 있는 문자열을 반환
        System.out.println(Seasons.FALL.name());

        // valuesOf() 주어진 문자열의 열거 객체를 반환
        System.out.println(Seasons.valueOf("WINTER"));

        // values() 열거 객체들을 배열로 반환
        System.out.println(Arrays.toString(Seasons.values()));

        // ordinal() 열거 객체의 순번(0부터 시작)을 반환
        System.out.println(Seasons.SUMMER.ordinal());

        // compareTo() : 매개값과 비교해 순번 차이를 반환
        System.out.println(Seasons.SPRING.compareTo(Seasons.WINTER));
    }
}

제네릭(Generic) :

하나의 클래스로 모든 타입의 데이터를 저장할 수 있는 인스턴스를 만들 수 있음

  • T의 타입은 기본 데이터 타입을 하나의 객체로 다룰 수 있게 해주는 wrapper class을 사용
  • 타입 지정에 제한이 없다. -> 클래스 타입도 가능
class Test<T> { // T의 타입은 클래스의 인스턴스가 생성될때 정해짐
    private T item;

    public Test(T item) {
        this.item = item;
    }
    public T getItem() {
        return item;
    }
    public void setItem(T item) {
        this.item = item;
    }
    public T testMethod(T something) {
        return something;
    }
    public <T> void genericMethod(T element) {
    } //제네릭 메서드
    // T의 타입은 메서드가 호출될 때 정해진다.
    // 클래스 옆의 T와 다름
}
public class GenericTest {
    public static void main(String[] args) {
        Test<String> stringClass = new Test<>("str");
        Test<Integer> intClass = new Test<>(300);
    }
}

  • T의 타입에 제한을 둘 수도 있음
class ClassName<T extends UpperClassName> {
}
// 해당 클래스의 하위 클래스들만 타입으로 지정할 수 있게 된다.
// 인터페이스의 경우에도 타입으로 지정 가능하며 양식은 동일하게 extends 키워드 사용
// 특정 클래스를 상속받고 동시에 특정 인터페이스를 구현한 클래스 타입만 지정하려면 & 연산자를 사용
  • 와일드 카드를 이용한 타입 제한
<? extends T> // T와 T를 상속받은 하위 클래스만 타입으로 받을 수 있다.
<? super T> // T와 T의 상위 클래스만 타입으로 받을 수 있다.

예외 처리(Exception Handling)

예기치 못한 에러에 대응할 수 있도록 미리 작성해 프로그램의 비정상적인 종료를 막고 정상적으로 실행하기 위해 작성

  • 컴파일 에러 : 컴파일 중 발생하는 에러

    • 문법적인 문제, 상대적으로 쉽게 발견 및 수정 가능
    • 자바 컴파일러에 의해 발견
  • 런타임 에러 : 런타임 중 발생하는 에러

    • 컴퓨터가 수행할 수 없는 작업을 요청할 때 발생
    • 자바 가상 머신(JVM)에 의해 감지
  • 에러(error) : 복구하기 어려운 수준의 심각한 오류 // 메모리 부족(OutOfMemoryError), 스택오버플로우(StackOverflowError) 등

  • 예외(exception) : 잘못된 사용, 코딩으로 상대적으로 미약한 수준의 오류

  • 자바에서는 예외가 발생하면 예외 클래스로부터 객체를 생성해 해당 인스턴스를 통해 예외를 처리한다.
    Throwable 클래스에서 확장되어 Errors 와 Exceptions 클래스로
    Exceptions 클래스에서 Runtim Exceptions 와 Other Exceptions로 확장

public class ExceptionTest {
    public static void main(String[] args) {
       try {
           //throw new ArithmeticException(); 의도적으로 예외 발생시키기

           System.out.println("소문자를 대문자로");
           printMyName(null); // 예외 발생
           printMyName("aaaaa"); // 실행되지 않고 바로 catch로 넘어간다
           //exMethod();
       }
       catch (ArithmeticException e) {
           System.out.println("ArithmeticException 발생!");
       }
       catch (NullPointerException e) {
           System.out.println("NullPointerException 발생!");
           System.out.println("e.getMessage : " + e.getMessage()); // 예외 정보 출력
           System.out.println("e.toString : " + e.toString()); // 예외 정보 출력
           e.printStackTrace(); // 예외 정보 출력
       }
       finally { // 예외 발생 여부에 상관없이 무조건 실행
           System.out.println("[프로그램 종료]");
       }
    }
    static void printMyName(String str) {
        String upperCase = str.toUpperCase();
        System.out.println(upperCase);
    }
    //static void exMethod() throws Exception{}
    //메서드에서 발생한 예외의 처리를 메서드를 호출한 곳으로 던진다.
}

컬렉션 프레임워크(Collection Framework)

자료 구조를 바탕으로 객체들을 효율적으로 관리할 수 있게 컬렉션(여러 데이터의 집합)을 만들고 자료 구조에 데이터를 추가, 삭제, 수정, 검색 할 수 있는 메서드를 포함한 인터페이스와 클래스

list interface

  • 배열과 같이 객체를 일렬로 늘어놓는 구조
  • 객체를 저장하면 자동으로 인덱스가 부여
  • 인덱스로 객체 검색, 추가, 삭제 등
  • 메서드

ArrayList class

  • 배열과 유사
  • 저장 용량을 초과하여 객체가 추가되면 자동으로 저장용량이 늘어남
  • 데이터가 연속적으로 존재
  • 데이터 검색이나 순차적으로 추가 혹은 삭제 하는 경우 효율적
  • 데이터 개수가 변하지 않을때
  • 메서드
import java.util.ArrayList;

public class ArrayListTest {
    public static void main(String[] args) {
    
        ArrayList<String> list = new ArrayList<String>();

        //String 타입의 데이터를 ArrayList에 추가
        list.add("apple");
        list.add("beer");
        list.add(1,"carrot");

        // set() 해당 인덱스의 요소 교체
        list.set(0, "cat");

        // size()저장된 총 객체 수
        int size = list.size();
        System.out.println(size); // -> 3

        // get() 해당 인덱스의 객체 얻기
        String skill = list.get(0);
        System.out.println(skill);  // -> cat

        for (int i = 0; i < list.size(); i++) {
            String str = list.get(i);
            System.out.println(i + " : " + str);
        }
        for (String str : list) {
            System.out.println(str);
        }
        // remove() : 인덱스 객체 삭제
        list.remove(0);
        System.out.println(list.get(0));   // -> carrot

        list.remove("carrot");
        System.out.println(list.get(0));   // -> beer

        // clear() : 인덱스의 요소들을 모두 제거
        list.clear();

        // contains() : 해당 요소를 갖고있는지 확인하여 boolean값 리턴
        System.out.println(list.contains("apple"));   // -> false
        
        // clone() : ArrayList와 동일한 요소들을 가진 ArrayList 생성
        // clone() 메서드는 Object 클래스에서 상속받은 메서드이기 때문에 
        // 반환된 객체를 ArrayList 타입으로 캐스팅해주어야 한다.
        ArrayList<String> clonedList = (ArrayList<String>) list.clone();
    }
}

LinkedList class

  • 데이터가 불연속적으로 존재
  • 데이터가 서로 연결되어 있음
  • 각 요소들은 연결된 이전 요소와 다음 요소의 주소값과 데이터로 구성
  • 데이터를 추가, 삭제할 경우 해당 요소를 앞뒤 요소와 연결해주면 되어 처리 속도가 빠름
  • 데이터를 중간에 추가, 삭제하는 경우 효율적
  • 데이터가 자주 변경될 때
  • 메서드
import java.util.LinkedList;

public class LinkedListTest {
    public static void main(String[] args) {

        LinkedList<String> list = new LinkedList<>();

        list.add("human");
        list.add("dog");
        list.add("cat");
		
        // size()
        int size = list.size();
        System.out.println(size); // -> 3

		// get()
        String str = list.get(0);
        System.out.println(str);  // -> human

        for(int i = 0; i < list.size(); i++) {
            String str2 = list.get(i);
            System.out.println(i + " : " + str2);
        }
        for(String str2 : list) {
            System.out.println(str2);
        }
        // remove()
        list.remove("human"); // 객체 직접 지정 가능
        list.remove(0); // 인덱스로 지정 가능
        System.out.println(list.get(0)); // -> cat
    }
}

Iterator

컬렉션에 저장된 요소들을 순차적으로 읽어오는 역할
Iterator 인터페이스에 정의, Collection 인터페이스에 메서드 iterator() 정의

  • Collection 인터페이스를 상속받는 List Set인터페이스를 구현한 클래스는 iterator() 메서드 사용 가능
import java.util.Iterator;
import java.util.LinkedList;

public class IteratorTest {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>();

        list.add("red");
        list.add("green");
        list.add("blue");

        Iterator<String> stringIterator = list.iterator();

// hasnext() : 다음 객체가 있을 시 true 리턴
        while (stringIterator.hasNext()) {
            System.out.println(stringIterator.next());
        }
        
// remove() : next()로 불러온 객체를 삭제
        while (stringIterator.hasNext()) {
            String str = stringIterator.next();
            if (str.equals("red")) {
                stringIterator.remove();
            }
        }
    }
}

set interface

  • 요소의 중복을 허용하지 않고 저장 순서를 유지하지 않음
  • 메서드

HashSet class

객체를 추가하고자 할때 저장하고자 하는 객체의 해시코드와 저장되어 있는 객체들의 해시코드를 비교하여 같은 해시코드가 없을때 객체를 추가

-hashCode()로 해시코드 확인, equals()로 비교

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

public class HashSetTest {
    public static void main(String[] args) {
        HashSet<String> colour = new HashSet<>();

        languages.add("red");
        languages.add("orange");
        languages.add("yellow");
        languages.add("green");
        languages.add("red"); // 중복 -> 추가되지 않음

        Iterator it = languages.iterator();

        while(it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

TreeSet class

  • 정렬과 검색에 특화된 이진 탐색 트리 구조
  • 최상위 노드는 루트
  • 요소 추가시 사전 편찬 순서에 따라 오름차순으로 정렬
  • 메서드
import java.util.TreeSet;

public class TreeSetTest {
    public static void main(String[] args) {

        TreeSet<String> alphabet = new TreeSet<>();

        alphabet.add("Aa");
        alphabet.add("Bb");
        alphabet.add("Cc");

        System.out.println(alphabet);
        System.out.println(alphabet.first()); // 가장 작은, 첫번째 요소를 반환
        System.out.println(alphabet.last()); // 가장 큰, 마지막 요소를 반환
        System.out.println(alphabet.higher("Aa")); // 해당 요소 다음 큰 요소를 반환 (마지막 요소 지정시 null)
        System.out.println(alphabet.subSet("Aa", "Cc")); // fromElement toElement전까지 요소를 반환
    }
}

Map interface

키(key)와 값(value)로 구성된 객체를 저장하는 구조
이 객체는 Entry객체이며 키와 값을 Key객체와 Value객체로 저장

  • 키는 중복될 수 없지만 값은 중복 저장 가능
  • 저장된 키와 같은 키로 값을 저장하면 기존의 값이 새로운 값으로 교체
  • 순회하며 값을 처리해야 할때 entrySet()이나 keySet() 메서드를 이용하여 Set 형으로 변환 후 반복문 실행
  • 메서드

HashMap class

  • 해시 함수를 통해 키와 값이 저장되는 위치를 결정
  • 삽입되는 순서와 위치가 관계가 없음
  • 많은 양의 데이터 검색에 효율적
  • 키와 값의 타입을 따로 지정
  • 메서드
import java.util.*;

public class HshMapTest {
    public static void main(String[] args) {

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

        map.put("철수", 75);
        map.put("영희", 90);
        map.put("유진", 85);
        map.put("희성", 80);
        map.put("동매", 95);

//         저장된 entry 수
        System.out.println("총 entry 수 : " + map.size());

//         객체 찾기
        System.out.println("철수 : " + map.get("철수"));
        System.out.println();

//         객체 삭제
        map.remove("철수");
        System.out.println("총 entry 수 : " + map.size());


//        forEach문을 사용해 값 읽기
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + " : " + value);
        }
        System.out.println();

//         key를 요소로 가지는 Set을 생성
        Set<String> keySet = map.keySet();
//        keyset을 순회하며 value를 읽어온다
        Iterator<String> keyIterator = keySet.iterator();
        while(keyIterator.hasNext()) {
            String key = keyIterator.next();
            Integer value = map.get(key);
            System.out.println(key + " : " + value);
        }
        System.out.println();

//        Entry 객체를 요소로 가지는 Set을 생성
        Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
//         entrySet을 순회하며 value를 읽어온다
        Iterator<Map.Entry<String, Integer>> entryIterator = entrySet.iterator();
        while(entryIterator.hasNext()) {
            Map.Entry<String, Integer> entry = entryIterator.next();
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + " : " + value);
        }

        // 객체 전체 삭제
        map.clear();
    }
}
  • Map 순회 방법 두가지
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class IteratorTest2 {
    public static void main(String[] args) {

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

        hashMap.put("aaa", 572);
        hashMap.put("bbb", 13);
        hashMap.put("ccc", 62);
        hashMap.put("ddd", 9);
        hashMap.put("eee", 48);

        for (Map.Entry <String, Integer> entry : hashMap.entrySet()) {
            String key = entry.getKey();
            Integer value = entry.getValue();

            System.out.println(key + " : " + value);
        }
        System.out.println();

        Iterator<Map.Entry<String, Integer>> entryIterator = hashMap.entrySet().iterator();
        while (entryIterator.hasNext()) {
            String key = entryIterator.next().getKey();
            int value = hashMap.get(key);
            System.out.println(key + " : " + value);
        }
    }
}

0개의 댓글