jhhan의 블로그

Java의 정석을 시작하자(4)(2/7) 본문

JAVA

Java의 정석을 시작하자(4)(2/7)

jhhan000 2020. 2. 13. 15:05

11장. 컬렉션 프레임웍(Collection Framework)

-컬렉션 프레임웍 : 데이터 군을 저장하는 클래스들을 표준화한 설계

  • 컬렉션을 다루기 위한 표준화된 프로그래밍 방식
  • 편의를 위해 다양한 클래스 제공
  • java.util패키지에 포함되어 있다.
  • ex) Vector, ArrayList, HashSet 등

-핵심 인터페이스

인터페이스 특징
List

-순서가 있는 데이터 집합

-데이터 중복 허용

ex) Vector, ArrayList, LinkedList, Stack 등

Set

-순서가 없는 데이터 집합

-데이터 중복 허용 안함

ex) HashSet, TreeSet 등

Map

key와 value의 pair로 이루어진 데이터 집합

key는 중복 허용 안함

value는 중복 허용

ex) HashMap, TreeMap, HashTable, Properties 등

  • List 와 Set은 공통부분이 많아서 Collection이라는 인터페이스로 정의할 수 있다.

-ArrayList

  • 가장 많이 사용되는 컬렉션 클래스
  • Vector를 개선 -> Vector보다 ArrayList를 쓸 것을 권장
  • 장점 : 1. 구조 간단  2. 데이터 읽는 시간 짧음
  • 단점 : 1. 크기 변경 안됨  2. 데이터의 추가/삭제 오래 걸림

ArrayList 예제

** 예제를 출력한 것이다.

** sort를 사용해서 ArrayList를 정렬할 수도 있다.

** retainAll() : 공통된 것들만 남기고 나머지는 다 삭제하는 메서드

 

 

-LinkedList

  • 배열의 단점을 보완하기 위해 등장
  • 데이터 추가/삭제 용이
  • 데이터 읽는 시간이 길다.
  • 데이터 개수가 변하지 않으면 ArrayList, 데이터 개수 변경이 잦으면 LinkedList 사용 권장

-Stack & Queue

  • Stack : LIFO(Last In First Out)구조.
  • ArrayList 같은 배열기반의 컬렉션 클래스 사용
  • Stack 클래스가 따로 존재
  • Queue : FIFO(First In First Out)구조.
  • LinkedList로 구현하는 것이 더 적합
  • Queue클래스가 별도로 존재하지 않는다.
  • 대신 Queue인터페이스를 구현한 클래스들이 있음 -> 그것들을 사용해서 진행
  • LinkedList가 대표적인 Queue인터페이스를 구현한 클래스이다.

-Iterator : 컬렉션에 저장된 요소들을 읽어오는 방법을 표준화 한 것

  • iterator()를 호출해서 사용
  • iterator : 기본
  • Enumeration : iterator 구버전
  • ListIterator : iterator에 양방향 조회기능 추가, iterator기능을 향상한 것이다.

iterator 예제

  • 예제의 결과는  1 2 3 4 5가 출력된다.

-Comparable & Comparator

  • Comparable : 기본 정렬기준을 구현하는데 사용
  • Comparator : 기본 정렬기준 외에 다른 기준으로 정렬할 때 사용
  • 2개 모두 인터페이스이다.
  • Comparator의 경우 상속해서 새로운 정렬 기준을 만든다.
  • compare(), compareTo() 모두 사용 가능

  • Comparator를 사용한 예제이다.
  • 문자열의 경우 대소문자를 구분해서 정렬을 한다.
  • 따라서 대문자나 소문자만 사용해야 원하는 정렬결과를 얻을 수 있다.
  • 혹은 CASE_INSENSITIVE_ORDER를 사용하면 대소문자 구분하지 않고 정렬한다.

-HashSet

  • Set인터페이스를 구현한 가장 대표적인 컬렉션
  • 저장순서를 유지하지 않는다.
  • 순서 유지를 원한다면 LinkedHashSet을 사용해야 한다.
  • add(), addAll()메서드로 새로운 요소 추가 -> 이 때 중복이 있다면 추가하지 않는다.
  • equals(), hashCode()가 오버라이딩 되어 있음.
  • equals()로 true를 얻으면 hashCode()도 true가 나오게 해야 한다.

  • HashSet을 이용한 예제이다.
  • A집합과 B집합을 이용해 교집합, 합집합, 차집합을 구해보았다.

-TreeSet

  • 이진검색트리 라는 자료구조의 형태로 데이터를 저장하는 컬렉션 클래스
  • TreeSet은 '레드-블랙 트리(Red-Black Tree)'로 구현되어 있다.
  • 범위검색, 정렬에 유리하다.
  • 데이터의 추가/삭제는 오래 걸리는 편이다.

  • TreeSet을 이용한 예제이다.
  • 이진검색트리 기반이어서 자동으로 정렬을 해준다.

-HashMap & HashTable

  • HashTable을 개선한 것이 HashMap
  • HashMap을 사용할 것을 권장
  • HashMap : Map인터페이스를 구현한 대표적인 컬렉션 클래스
  • HashMap을 이용해서 구현한 것이 HashSet
  • Hash기법으로 데이터 저장 -> 데이터 검색이 빠르다.
  • 순서유지를 원한다면 LinkedHashMap을 이용해야 한다.

  • HashMap을 이용한 예제이다.
  • 4명의 학생들의 점수에 대해 여러가지로 출력한 예제이다.
  • Key는 중복을 허용하지 않기 때문에 마지막에 들어간 값이 적용된 것을 볼 수 있다.

-TreeMap

  • TreeSet과 비슷하다.
  • TreeMap을 이용하여 구현한 것이 TreeSet이다.
  • Map을 쓸 때는 주로 HashMap이용
  • 정렬이나 범위검색은 TreeMap이 더 좋다.

 

12장. 지네릭스, 열거형, 애너테이션

(지네릭스 부분은 어려워서 제대로 정리가 안 될 수도 있지만, 그래도 최선을 다해 정리할 것이다.)

1. 지네릭스

  • 컴파일 시 타입 체크(compile-time type check)를 해주는 기능
  • 장점 : 1. 타입 안정성 향상  2. 형변환 생략 가능
  • 작성 시 Object 대신 T 같은 타입변수 사용(T는 Type의 첫글자를 따서 사용)
  • T 대신 실제 타입 지정시 형변환 생략이 가능하다

-지네릭스 용어 정리

  • ex) class Box<T> {} 라는 클래스 정의 했을 때
  • Box<T> : 지네릭 클래스이다. 'T의 Box' 또는 'T Box'라고 읽는다.
  • T : 타입 변수 또는 타입 매개변수
  • Box : 원시 타입(raw Type)

  • 지네릭 타입의 예제이다.
  • tvList가 printAll()에서 사용되기 위해서는 '와일드 카드'가 필요한 부분인데 조금 있다가 나오므로 그 때 가서 확인한다.

-Iterator<E>

  • Iterator에도 지네릭스가 적용될 수 있다.

  • 이터레이터에 대한 예제이다.
  • 지네릭스가 추가되었을 뿐 큰 차이는 없다.

-HashMap<K,V>

  • HashMap의 경우 Key와 Value의 첫 글자를 따서 <K,V>로 표현했다.
  • ex) HashMap<String, Integer> map = new HashMap<String, Integer>();

-제한된 지네릭 클래스

  • extends를 사용해서 특정 타입의 자손들만 대입할 수 있게 한다.
  • 인터페이스를 구현하더라도 extends를 사용한다.(implements 사용안함)

  • 제한된 지네릭 클래스에 대한 예제이다.
  • 조금 복잡하긴 하지만 이렇게 하면 fbox에 다양하게 담을 수 있게 된다.

-지네릭스의 제약

  • static멤버에는 타입변수 T를 사용할 수 없다. -> T는 인스턴스변수로 간주되기 때문이다.
  • 지네릭 배열 타입의 참조변수 선언은 가능
  • new T[10] 같은 배열 생성은 할 수 없다.
  • ex) T[] tmpArr = new T[10];  // 에러

-와일드 카드

  • 지네릭 타입에 다형성을 적용할 수 있게 해준다.
<? extends T> 와일드 카드의 상한 제한
T와 그 자손들만 가능
<? super T> 와일드 카드의 하한 제한
T와 그 조상들만 가능
<?> 제한 없음.
모든 타입 가능
<? extends Object>와 동일

  • 와일드 카드의 예제이다.
  • 역시 예제가 복잡하다. 하지만 와일드 카드를 토애 fb에 다양한 fruit이 들어갈 수 있다.

-지네릭 메서드

  • 지네릭 타입의 선언 위치 : 반환 타입 바로 앞
  • ex) static <T> void sort(List<T> list, Comparator<? super T> c)
  • 메서드에 선언된 지네릭 타입 = 지역 변수를 선언한 것과 같다.
  • 위의 예제에서 makeJuice() 메서드를 지네릭 메서드로 바꿀 수 있다.
  • ex) static <T extends Fruit> Juice makeJuice(FruitBox<T> box) 로 바꿀 수 있다.

-지네릭 타입의 형변환

  • 지네릭 타입과 원시 타입 간의 형변환? -> 가능하다. 경고가 발생할 뿐

-지네릭 타입의 제거

  • 제거하는 것은 꽤 복잡하다. 그래서 기본적인 제거 과정만 다룬다.
  • 1. 지네릭 타입의 경계(bound)를 제거한다.
  • 2. 타입이 일치하지 않으면, 형변환을 추가한다.

2. 열거형

-열거형 : 여러 상수를 선언할 때, 편리하게 선언할 수 있는 방법

  • 정의 방법 :  enum 열거형이름 { 상수명1, 상수명2, ... }
  • 사용법 : 열거형이름.상수명

-열거형의 조상

  • java.lang.Enum에 정의되어 있다.
  • 정의된 순서부터 정수로 반환된다.(시작은 0)

-열거형의 예제이다.

- 이렇게 쓸 수 있다는 것을 알아두자.

-열거형에 멤버 추가하기

  • 불규칙적인 경우에 대비해서 사용한다.
  • 위의 예제를 응용해보겠다.
  • ex) enum Direction { EAST(1), SOUTH(5), WEST(-1), NORTH(10) }

3. 애너테이션

- 애너테이션 : 프로그램의 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시키는 것

  • 주석처럼 프로그래밍 언어에 영향을 미치지 않는다.
  • 다른 프로그램에게 유용한 정보 제공을 한다.
  • 보통 새로 정의하는 것보다 기존의 것들을 사용하는 경우가 더 많다.

- @Override

  • 오버라이딩 된 메서드라는 의미이다.
  • 컴파일러가 같은 이름의 메서드가 조상에 있는지 확인하고 없으면 에러메시지를 출력한다.
  • 필수는 아니지만 실수를 방지할 수 있으므로 꼭 붙이도록 하자.

-@Deprecated

  • 더 이상 사용되지 않는 필드나 메서드에 붙인다.
  • 그러므로 더 이상 사용하지 않을 것을 권장한다.
  • 강제는 아니므로 사용해도 된다. 하지만 사용하지 않도록 한다.

-@FunctionalInterface

  • 이 애너테이션이 붙으면 컴파일러가 '함수형 인터페이스'르 올바르게 선언했는지 확인한다.
  • 실수를 방지할 수 있으므로 붙이도록 하자.

-@SuppressWarnings

  • 컴파일러가 보여주는 경고메시지를 나타나지 않게 해준다.
  • 주로 쓰는 것 : deprecation, unchecked, rawtypes, varargs
  • deprecation : @Deprecated가 붙은 대상을 사용해서 나타나는 경고 억제
  • unchecked : 지네릭스로 타입을 지정하지 않았을 때 나타나는 경고 억제
  • rawtypes : 지네릭스를 사용하지 않아서 발생하는 경고 억제
  • varargs : 가변인자의 타입이 지네릭 타입일 때 발생하는 경고 억제

-애너테이션의 조상

  • Annotation이 모든 애너테이션의 조상
  • 하지만 상속이 허용되지 않는다.

-애너테이션 요소의 규칙

  • 애너테이션의 요소를 선언할 때 지켜야 하는 규칙
    1. 요소의 타입은 기본형, String, enum, Class, 애너테이션 만 허용
    2. () 안에 매개변수 선언 X
    3. 예외 선언 안 됨
    4. 요소를 타입 매개변수로 정의 X

 

 

13장을 여기다 추가할까 말까 고민중이다.