코드스테이츠 16일차

안형준·2022년 5월 17일
0

코드스테이츠

목록 보기
16/32
post-thumbnail

1차 학습목표

제네릭의 장점을 이해하고 제네릭 클래스를 정의할 수 있다.
특정 메서드만 제네릭으로 선언하여 사용할 수 있다.

제네릭의 장점은?
1. 타입체크와 형변환을 생략해서 간결한 코드 작성이 가능하다.
2. 클래스나 메서드 내부에서 사용되는 객체의 타입 안정성을 제공한다.

👻지네릭스란?
- Generics : 컴파일 시 타입을 체크 해주는 기능
* Error : ClassCastException : 형변환 에러
- 컴파일 에러 > 실행 시 에러
- 실행시 발생하는 에러를 컴파일 단으로 끌고올 수 있을까 ? -> 지네릭스의 탄생
- 지네릭스의 사용으로 형변환 생략 가능, 타입 체크 강화, Object쓰면 레거시 처럼 여러 객체 사용 가능

👻타입 변수
- 타입변수 : 클래스 작성 시 <E>와 같은 타입변수를 주어 작성한다.
- 타입변수 대입 : 참조변수와 생성자에 실제타입을 지정해주어야 한다.
-> 한번에 변경되기 때문에 형변환은 따로 해주지 않아도 된다.

👻지네릭스용어, 지네릭 타입과 다형성
1. 참조변수와 생성자의 대입된 타입(타입 매개변수)은 일치(상속관계여도 안됨 무조건 일치해야함)
2. 지네릭 ‘클래스’간의 다형성은 성립된다(다형성: 조상 클래스의 참조변수로 자손 클래스의 객체를 다룰수 있다.)
3. 매개변수의 다형성도 성립

👻Iterator, HashMap과 지네릭스
- Iterator<E> : 클래스 작성 시 Object타입 대신 T와 같은 타입 변수 사용
- HashMap<K, V> : 여러 개의 타입 변수가 필요한 경우, 콤마 구분자

👻제한된 지네릭 클래스, 지네릭스의 제약
- 제한된 지네릭 클래스 : extends로 대입할 수 있는 클래스 제한
-> class FruitBox<T extends Fruit> { ... // Fruit의 자손만 타입으로 대입 가능 }
- interface인 경우에도 extends 사용
- 지네릭스의 제약
1) 타입변수의 대입은 인스턴스 별로 다르게 가능
2) static 멤버에 타입 변수 사용 불가 -> 모든 인스턴스에 공통
3) 배열 생성할 때 타입 변수 사용 불가. 타입 변수로 배열 선언은 가능 -> new T(불가 x) - 객체생성 x, 배열생성 x(타입이 확정적이기 못하기 때문에)

👻와일드카드, 지네릭 메서드
- 와일드 카드 <?> : 하나의 참조 변수로 대입된 타입이 다른 객체를 참조 가능 (지네릭 타입 일치 조건을 맞추는 번거로움을 해결하고자 등장), 지네릭의 다형성
- <? extends T> : 와일트 카드의 상한 제한, T와 그 자손들만 가능
- <? super T> : 와일드 카드의 하한 제한, T와 그 조사들만 가능
- <?> : 제한 없음. 모든 타입이 가능, <? extends Object> 와 동일

- 지네릭 메서드
- 메서드 선언부에 선언된 메서드를 지네릭 메서드라 한다.
- 지네릭 메서드의 선언 위치는 반환 타입 바로 앞이다.
- 지네릭 클래스에 정의된 타입 매개변수가 T이고, 지네릭 메서드에 정의된 타입 매개변수가 T이더라도 이 둘은 전혀 별개의 것이다.
- 지네릭 메서드는 꼭 지네릭 클래스가 아닌 일반 클래스에도 정의될 수 있다.
- 원래는 static 멤버에는 타입 매개변수를 사용할 수 없지만, 메서드에 지네릭 타입을 선언하고 사용하는 것은 가능하다.

👻지네릭 형변환
- 지네릭 타입의 형변환 : 지네릭타입과 원시 타입간의 형변환은 가능은 하지만 바람직 하지 않다. (경고 발생)
-> 지네릭 타입 --> 원시타입(경고 발생), 원시 타입 --> 지네릭 타입(경고 발생)
-> Box<String> --> Box<Object> or Box<String> --> Box<Object> 는 형변환 안됨(에러)

- 지네릭 타입의 제거 : 하위호환성과 안정성 문제 때문에 자바 컴파일러는 지네릭 타입을 제거하고 필요한 곳에 형변환을 넣는다.
1) 지네릭 타입의 경계(bound)를 제거(T -> Object or 제한된 타입)
2) 지네릭 타입 제거 후에 타입이 불일치 하면 형변환을 추가
3) 와일드 카드가 포함된 경우엔, 적절한 타입으로 형변환 추가

2차 학습목표

컬렉션 프레임워크의 핵심 인터페이스를 이해하고 사용할 수 있다.
주요 인터페이스와 컬렉션 클래스의 핵심 메서드를 사용할 수 있다.
필요에 따라 어떤 인터페이스와 컬렉션 클래스를 사용할지 이해할 수 있다.

👻컬렉션프레임웍과 핵심 인터페이스
- 컬렉션(collection) : 여러 객체(데이터)를 모아 놓은 것
- 프레임웤(framework) : 표준화, 정형화된 체계적인 프로그래밍방식, 생산성을 올려줌, 등장 배경을 이해하면 프레임웤을 사용하는 이유를 저절로 알게 됨
ex) collection framework, django framework, spring framework

- 라이브러리 : 정보, 책, 오디오 라이브러리 등 -> 기능만 제공

- 컬렉션 프레임웤 : 컬렉션(다수의 객체)을 다루기 위한 표준화된 프로그래밍 방식, java.util패키지에 포함, jdk1.2부터제공

- List : 순서 O, 중복 O
ex) 대기자 명단
* 구현 클래스 : ArrayList, LinkedList, Stack, Vector
- Set : 순서X, 중복X ex) 양의 정수 집합, 소수의집합
* 구현클래스 : HashSet, TreeSet
- Map : key, value쌍, 순서X, 중복(키X, 값O)
ex) 우편번호, 지역번호(전화번호)
* 구현클래스 : HashMap, TreeMap, HashTable(legacy), Properties(legacy)

👻Collection, List, Set, Map
Collection인터페이스

List인터페이스(순서O, 중복O: ArrayList, LinkedList..)
-List subList(from, to): 일부 반환

Set인터페이스(순서X, 중복X: HashSet, TreeSet..)
-boolean을 반환하는 집합 관련 메서드

Map인터페이스(순서X, 키중복X, 값중복O: HashMap, TreeMap..)
-LinkedHashMap: 순서O
-HashTable: old, 동기화(HashMap 별도 처리)
-put(key, value) / putAll(Map)
-Set entrySet(), Set keySet(), Collection values()

👻ArrayList
- ArrayList: Vector를 개선한 것, 배열기반으로 데이터 저장, 순서와 중복 O, 객체만 저장가능
list1.remove(1): 인덱스가 1인 객체를 삭제  VS list1.remove(new Integer(1)): 1을 삭제. 
- 삭제과정
1. 삭제할 데이터의 아래에 있는 데이터를 한 칸씩 위로 복사해서 삭제할 데이터를 덮어쓴다.
2. 데이터가 모두 한 칸씩 위로 이동하였으므로 마지막 데이터는 null로 변경해야한다.
3. 데이터가 삭제되어 데이터의 개수(size)가 줄었으므로 size의 값을 1 감소시킨다.

만약 반복문으로 삭제하게 될 때
첫번째부터 삭제한다면 배열복사가 발생하여 모두 지워지지 않는다.
하지만 마지막부터 삭제한다면, 배열 복사가 발생되지 않아 모두 지워지게 된다.

👻LinkedList
- 배열의 장단점 : 
(장) - 구조간단, 데이터를 읽는 데 걸리는 시간 짧음, 순차적 데이터 추가, 삭제는 빠름
(단) - 크기변경 어려움(배열 새로 생성 : 더 큰 배열 생성, 기존 내용 복사), 비순차적인 데이터 추가 삭제에 시간 많이 걸림

- LinkedList(배열의 단점을 보완) : 불연속적으로 존재하는 데이터를 연결 / 하나씩 연결된 기차라고 생각하자
* 데이터 삭제 : 단 한번의 참조변경만으로 가능
* 데이터 추가 : 한 번의 Node객체 생성, 두 번의 참조변경으로 가능
- ArrayList vs LinkedList 비교 -> Array 와 LinkedList DS비교와 동일

👻Stack과 Queue
- Stack : LIFO, push, pop, 순차적 추가 / 삭제가 가능한 배열 사용해 구현
- Queue : FIFO, offer, poll, 링크드 리스트가 더 적합(삭제 - 추출에 더 유리, 자리이동이 없으므로)
- Stack&Queue에서 peek : 맨 위의 저장된 객체를 본다.(반환)
search : 0이 아닌 1부터 시작
- Queue에서 add, remove : 예외발생O
- Queue에서 offer, poll : 예외발생X
- Queue는 interface로 정의 됨 -> 객체 생성 불가 : Queue직접 구현, 구현된 클래스 사용

👻Stack, Queue 활용
- 스택 활용 예 : 수식계산, 수식괄호검사, 워드프로세서 undo/redo, 웹브라우저 뒤로/앞으로
- 큐의 활용 예 : 최근사용문서, 인쇄작업 대기목록, 버퍼

👻Iterator, Enumeration, Map과 Iterator
- Iterator, ListIterator, Enumeration(legacy) : 컬렉션에 저장된 데이터를 접근하는데 사용되는 인터페이스
ListIterator는 Iterator의 접근성 향상 (양방향)
* 컬렉션에 저장된 요소를 읽어오는 방법 표준화 : hasNext()(확인), next()(읽기)
- Iterator는 끝까지 가고나면 다시 못돌아옴(1회용) -> 다시 얻어와야 한다
- 컬렉션 프레임워크를 종종 바꿔줘야하는 이슈가 있기에 Iterator를 사용
- Map은 Iterator가 없다. 대신에 keySet(), entrySet(), values() 사용하여 Iterator를 사용할 수 있다.

👻Arrays
- Arrays : 배열을 다루는데 편리하게 해주는 static 메서드 제공 : toString()(출력), copyOf(), copyOfRange()(복사), fill(), setAll()(람다식 들어감)(채우기), sort(), binarySearch() (정렬과 검색, bs는 정렬후에 해라)
- 순차검색과, 이진검색(SQL 튜닝의 그것과 연관, Full scan, Indexing)
- 다차원 배열의 출력 : deepToString()
- 다차원 배열의 비교 : deepEquals()
- asList() : 배열을 다루기 편리한 메서드(static) 제공: 읽기전용
- 람다스트림 관련 : parallelXXX(), spliterator(), stream()

👻Comparator와 Comparable
- Comparator, Comparable : 객체 정렬에 필요한 메서드를 정의한 interface
-> Comparable : 기본 정렬기준 구현
-> Comparator : 기본 정렬 기준 외 다른 기준으로 정렬하고자 할 때
- sort() : 두 대상에 대하여 1) 비교 2) 자리바꿈
- compare(), compareTo() : 두 객체의 비교 결과 반환, 같으면 0 오른쪽이 크면 -, 왼쪽이 크면 +
- Integer와 Comparable <- 기본 정렬 기준 제공
- 3항연산자가 속도가 빨라 조금 더 유리하다.

👻HashSet
HashSet
순서를 유지하지 않고, 중복을 허용하지 않는다. (list와 반대 특성)
HashSet과 TreeSet은 set 인터페이스를 구현한 대표적인 클래스
Set이 필요하다면 일반적인 HashSet을 사용하지만,
순서를 유지하고 싶다면 LinkedHashSet클래스를 사용한다.

HashSet - 주요 메서드 
HashSet(Colletion c) - 생성자를 가지고 있다.
지정 된 클래스에 모든 객체를 저장.
HashSet(int initialCapacity) - 초기용량 정하기 보통 두배로 늘린다.
언제 두배로 늘릴 것인지 정하는
HashSet(int initialCapacity, float loadFactor)

추가 삭제와 모두 삭제하는 메서드 
retainAll(Colletion c) - 조건부 삭제 . 교집합 구할 때 쓰인다.
addAll(Colletion c) - 합집합
removeAll(Colletion c) - 차집합

contains(Object o) - set이 해당 객체를 포함하고 있는데 true or false 반환
containsAll(Colletion c) - 컬렉션에 담긴 여러 객체가 모두 포함되어 있는지? True or false 반환 컬렉션으로 받는다.
이터레이터() - 컬렉션 요소 읽어오기 

이즈엠프티() - 비어있는지? 확인 
사이즈() - 저장 된 객체의 갯수 
투어레이(Object[] a) - set에 저장되어 있는 객체를 객체 배열로 반환

기본적으로 set은 정렬이 불가능한데 정렬을 하고싶다면 set의 모든 요소를 리스트에 저장한 후에 리스트를 정렬하면 된다.

- HashSet : 같은 객체가 없으면 저장, 있으면 저장X ex) add메서드를 실행 시 equals, hashCode를 호출
- equals, hashCode을 overriding하지 않으면 위 비교작업이 제대로 작동하지 않음

👻TreeSet
범위 검색(from~to)과 정렬에 유리한 컬렉션 클래스.
단점으로는 HashSet 보다 데이터 추가, 삭제에 시간이 더 걸린다. 

이진 탐색 트리(binary search tree)라는 자료구조 형태로 데이터를 저장하게 되는데,
이진트리는 나무와 비슷하게 생겼으면 구성되어 있는 각 하나를 노드라고 한다.
각 노드는 0~2개의 노드를 연결할 수 있다.
이진 탐색 트리는 부모노드의 왼쪽에는 부모노드의 값보다 작은 값을, 오른쪽에는 큰 값의 자식 노드를 저장하는 이진 트리이다.이처럼 정렬된 상태를 유지하기 때문에 단일 값 검색과 범위검색이 매우 빠르다.
하지만 링크드 리스트보다 데이터의 추가/삭제 시간은 더 걸린다. 대신 배열이나 링크드 리스트에 비해 검색과 정렬기능이 더 뛰어나다.

👻HashMap
- HashMap, HashTable(legacy) : 순서X, 중복(키X, 값O)
- 해싱의 원리 : 환자정보관리 예제 생각, 해시 함수를 이용해서 해시테이블에 있는 데이터 읽고 저장
- 해시테이블 : 배열과 링크드 리스트가 조합된 형태(chaining), 접근성과 변경의 유리를 섞은 형태
- 저장된 데이터를 가져오는 과정 : 키로 해시함수 호출하고 해시코드를 얻는다 -> 해시코드(해시f반환값)에 대응하는 링크드 리스트를 배열에서 찾는다 -> 링크드 리스트에서 키와 일치하는 데이터 탐색
-> 같은 키에 대해 같은 해시코드 반환해야 함, 서로 다른 키 일지라도 같은 값의 해시코드를 반환 할 수 있음

👻Collections클래스, 컬렉션 클래스 요약
- Objects(객체), Arrays(배열), Collections(컬렉션)
- 컬렉션의 동기화 : synchronizedXXX() ex) synchronizedCollection(Collection c), synchronizedList(List list)
- List syncList = Collections.synchronizedList(new ArrayList(...)); // 좌 : 동기화 된 리스트, 우 : 동기화 되지 않은 리스트
- 변경불가(readOnly) 컬렉션 만들기 : unmodifiableXXX()
- 싱글톤 컬렉션 만들기 : singletonXXX() // 객체 1개만 저장
- 한 종류의 객체만 저장하는 컬렉션 만들기 : checkedXXX() // 한 종류의 객체만 저장하는 컬렉션 ex) List checkedList = checkedList(list, String.class) // String만 저장 가능
- disjoint(list, newList) // 공통 요소가 있는지 확인할 때 사용하는 메서드

오늘은 컬렉션 프레임 워크와 제너릭에 대한 개념을 학습했다.
아마 지금까지 공부를 하면서 가장 절망을 많이 한 날이 아닌가싶다.
객체지향에 대한 개념도 가끔 흔들리는 부분이 있다보니 여러번 반복하면서 계속 복습해야할 것 같다.
지금 하고 있는 것들에 대한 개념이 확실하게 잡히지 않으면 미래에 스프링을 공부할 때 많이 힘들다는 얘기를 들었다. 그렇기에 나중에 가서 헷갈리지 않도록 확실하게 복습 할 예정이다.
오늘 정말 고생 많았고 내일도 파이팅!

profile
개발 공부

0개의 댓글