어제부로 객체지향 프로그래밍을 마치고 컬렉션에 들어간다. 그동안 클래스내부 코드를 쓸때 걱 타입마다 지정하여 선언하고 했었는데 컬렉션의 제네릭에서는 그럴 필요가 줄어든다고 해서 굉장히 획기적이라고 느꼈다. 제네릭을 배우고 나면 코딩이 한결 쉬워지겠지?! 이번 수업도 너무 기대된다!!!
학습목표
1.제네릭의 장점
2.제네릭 클래스 정의 및 활용
3.제네릭 메서드 정의 및 활용
제네릭 의미 : 일반적인.
자바에서의 제네릭 의미 : 타입을 추후에 지정할 수 있고 특정 데이터타입에 묶여있지 않게 일반화한것.
제네릭의 장점?
class Basket<T> { // T는 타입 매개변수. 참조형 타입.
private T item;
public Basket(T item) {
this.item = item;
}
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
public class BasketTest {
public static void main(String[] args){
Basket<String> basket1 = new Basket<String>("Hello");
Basket<Integer> basket2 = new Basket<Integer>(1);
Basket<Boolean> basket3 = new Basket<Boolean>(true);
Basket<Double> basket4 = new Basket<Double>(3.14);
// 타입변수 자리에 실제 타입 명시할때 래퍼클래스 사용!
// 생성하는 인스턴스마다 타입 지정.
// Basket<Double> basket4 = new Basket<>(3.14);
// 이 코드와 같이 구체적인 타입 생략 가능.
System.out.println(basket1.getItem());
System.out.println(basket2.getItem());
System.out.println(basket3.getItem());
System.out.println(basket4.getItem());
}
}
출력결과
> Hello
> 1
> true
> 3.14
타입 매개변수는 임의의 문자로 지정
T , K , V , E , N , R 자주사용
각각 Type, Key, Value, Element, Number, Result의 첫글자.
주의❗ 클래스변수에서는 타입매개변수 사용 불가!
이유? 클래스 변수는 모든 인스턴스가 공유하는 변수인데 클래스변수에서 타입매개변수를 사용하게되면 클래스 변수 타입이 인스턴스마다 변하게됨. 즉, 같은 변수를 공유하는게 아니게 됨.
제네릭 클래스를 사용할때 생성하는 인스턴스별로 타입을 지정해주어야함.
제네릭 클래스에 다형성 적용 가능
class Flower { ... }
class Rose extends Flower { ... }
class RosePasta { ... }
//제네릭 클래스 정의
class Basket<T> {
private T item;
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
//인스턴스화
public static void main(String[] args) {
Basket<Flower> flowerBasket = new Basket<>();
flowerBasket.setItem(new Rose()); // 다형성 적용
flowerBasket.setItem(new RosePasta()); // 에러
}
RosePasta는 Flower로부터 상속되지 않았기에 에러발생.
제네릭 클래스에 다형성을 적용하여 그 어떤 타입도 지정가능.
제네릭클래스를 정의할때
class Basket <T extends Flower>
이와 같이 정의하면 Flower의 하위 클래스만 타입으로 받음.
class Basket<T extends Plant>
class Basket <T extends Plant & Flower>
class Basket<T> { // 여기 선언된 T와
...
public <T> void add(T element){ //여기선언된 T는 서로 다른 매개변수로 간주.
}
}
Basket<String> basket = new Basket<>(); //class의 T가 String
basket.<Integer>add(10); // 메서드의 T가 Integer
basket.add(10);
지금까지 공부한것중에 가장 오랜 이해가 걸렸다. 생각보다 이해가 잘 안가서 많은 정보들을 찾아본것같다. 분명 엔지니어님께서 말씀하시기로는 다음 학습인 컬렉션 프레임워크가 힘들꺼라하셨는데 걱정이 많아지네...
학습목표
1.컬렉션 프레임워크의 핵심 인터페이스 이해 및 사용
2.주요 인터페이스와 컬렉션클래스의 핵심 메서드 사용
3.필요에 따라 어떤 인터페이스와 컬렉션클래스를 사용하는게 적합한지
컬렉션 프레임워크는 주요 인터페이스로 List,Set,Map 제공.
List
Set
Map
Collection : List와 Set의 공통점이 추출되어 추상화시킨것.
인터페이스 메서드
add(Object o) / addAll(Collection c) : 객체 및 컬렉션 객체들을 컬렉션에 추가. 리턴타입 boolean
contains(Object o) / containsAll(Collection c) : 객체 및 컬렉션 저장 여부 리턴. 리턴타입 boolean
Iterator() : 컬렉션의 iterator을 리턴. 리턴타입 iterator
equals(Object o) : 컬렉션 동일 여부 확인. 리턴타입 boolean
isEmpty() : 컬렉션 비어있는지 여부 확인. 리턴타입 boolean
size() : 저장된 전체 객체 수 리턴. 리턴타입 int
clear() : 컬렉션에 저장된 모든 객체 삭제. 리턴타입 void
remove(Object o) / removeAll(Collection c) : 객체 및 컬렉션 삭제 후 성공여부 리턴. 리턴타입 boolean
retainAll(Collection c) : 주어진 컬렉션 제외, 모든 객체를 컬렉션에서 삭제 및 컬렉션 변화 여부 리턴. 리턴타입 boolean
toArray() : 컬렉션에 저장된 객체를 객체배열로 반환. 리턴타입 Object[]
toArray(Object[] a) : 배열에 컬렉션의 객체 저장 후 반환. 리턴타입 Object[]
List인터페이스는 객체를 일렬로 늘어놓은 구조.
인덱스로 객체 관리.
인덱스로 객체 검색,추가,삭제 등 기능 제공
List 인터페이스 메서드
add(int index, Object element) : 인덱스에 객체 추가. 리턴타입 void
addAll(int index, Collection c) : 인덱스에 컬렉션 추가. 리턴타입 boolean
set(int index, Object element) : 인덱스위치에 객체추가. 리턴타입 Object
get(int index) : 인덱스에 저장된 객체 반환. 리턴타입 Object
indexOf(Object o) / lastIndexOf(Object o) : 순방향 / 역방향으로 탐색 후 주어진 객체 위치 반환. 리턴타입 int
listIterator() / listIterator(int index) : List의 객체 탐색하는 ListIterator 반환/ 주어진 인덱스부터 탐색할 수 있는 ListIterator 반환. 린턴타입 ListIterator
subList(int fromIndex, int toIndex) : from ~ to 까지의 인덱스에 있는 객체 반환. 리턴타입 List
remove(int index) : 인덱스에 저장된 객체 삭제 및 삭제한 객체 반환. 리턴타입 Object
remove(Object o) : 객체 삭제. 리턴타입 boolean
sort(Comparator c) : 비교자(comparator)로 list 정렬. 리턴타입 void
List 인터페이스 구현 클래스로는 ArrayList,Vector,LinkedList,Stack 등
ArrayList, LinkedList 가 가장 많이 사용
ArrayList : 기능은 Vector와 동일하지만 그보다 개선.
ArrayList에 객체를 추가하면 인덱스로 관리되고 저장용량 초과되면 자동으로 용량이 늘어남. 데이터 연속적 구성.
컬렉션 프레임워크 사용시 소스코드 최상당 패키기 밑에 import해야함.
LinkedList : 데이터를 효율적으로 추가, 삭제, 변경하기 위해 사용.
ArrayList와 LinkedList의 차이
ArrayList는 순차적으로 데이터를 추가,삭제,변경 하거나 데이터를 읽을때 유용
하지만 중간에 데이터를 추가하거나 삭제하기에는 번거로움.
LinkedList는 중간에 데이터를 추가,삭제,변경하기에 유용
즉 데이터에 잦은 변경이 있을땐 LinkedList, 데이터의 개수가 변하지 않을땐 ArrayList가 유용하다.
List인터페이스에서 인덱스로 객체를 검색, 추가, 삭제할 수 있는 기능을 제공.
Collection 인터페이스에서는 Iterator인터페이스를 구현한 클래스의 인스턴스를 반환하는 메서드인 iterator()가 정의돼있음.
Iterator 메서드
hasNext() : 읽어올 객체가 있으면 true, 없으면 false 리턴
next() : 컬렉션의 하나의 객체를 읽음. next()를 사용하기 전에 hasNext()로 읽어올 요소 있는지 확인해야함
remove() : next()로 읽어온 객체 삭제. next()호출한 다음에 remove()호출.
Set은 요소의 중복을 허용하지않고, 저장 순서를 유지하는 컬렉션.
Set 메서드
add(Object o) : 객체 추가, 성공하면 true 실패하면 false반환. 리턴타입 boolean
contains(Object o) : 객체가 Set에 존재하는지 확인. 리턴타입 boolean
isEmpty() : Set이 비어있는지 확인. 리턴타입 boolean
Iterator() : 저장된 객체를 하나씩 반환하는 반복자 리턴. 리턴타입 Iterator
size() : 저장된 전체 객체의 수를 리턴. 리턴타입 int
clear() : Set에 저장된 모든 객체 삭제. 리턴타입 void
remove(Object o) : 객체 삭제. 리턴타입 boolean
HashSet : Set인터페이스를 구현한 가장 대표적 컬렉션.
HashSet에 값 추가할때 중복값인지 판단 순서
add(Object o)를 통해 객체의 값을 저장하고자 함
저장하고자하는 객체의 해시코드를 hashCode()메서드로 얻어냄
Set이 저장하고있는 모든 객체의 해시코드를 hashCode()로 얻어냄
저장하고자하는 객체의 해시코드, Set에 이미 저장돼있는 객체들의 해시코드 비교
4-1. 같은 해시코드를 가진 객체가 존재하면 저장하고자했던 객체가 중복객체로 간주되어 Set에 추가X.add(Object o)가 true를 리턴.
4-2. 같은 해시코드를 가진 객체가 존재하지 않으면 Set에 저장하고자했던 객체가 추가되고 add(Object o)가 false를 반환
equals() 메서드로 객체 비교
5-1. true가 리턴되면 중복객체로 간주, Set에 추가X, add(Object o)가 true 반환
5-2. false가 리턴되면 Set에 객체 추가, add(Object o)가 false 반환
public class HashSetTest {
public static void main(String[] args) {
//HashSet 생성
HashSet<String> lang = new HashSet<String>();
//HashSet 에 객체 추가
lang.add("Java");
lang.add("Python");
lang.add("JavaScript");
lang.add("C++");
lang.add("Kotlin");
lang.add("Ruby");
lang.add("Java"); //중복
//반복자 생성하여 it에 할당
Iterator it = lang.iterator();
//반복자를 통해 HashSet을 순회하며 각 요소들을 출력
while(it.hasNext()){
System.out.println(it.next());
}
}
}
출력
Java
C++
JavaScript
Ruby
Python
Kotlin
출력순서도 뒤죽박죽이고 중복되는 Java는 추가되지않음
TreeSet
TreeSet은 이진탐색트리형태로 데이터 저장.
중복저장X,저장순서 바뀌는 Set인터페이스의 특징은 그대로임.
이진탐색트리의 최상위 노드는 루트
라고 함.
모든 왼쪽자식의 값이 루트나 부모보다 작고, 모든 오른쪽 자식의 값이 루트나 부모보다 크다는 특징.
TreeSet 메서드
TreeSet메서드
Map : Key는 중복저장 불가, Value는 중복저장 가능.
Map 인터페이스 구현 클래스는 HashMap, Hashtable, TreeMap, SortedMap 등
Map 메서드
HashMap
HashMap : Map인터페이스 구현 대표 클래스. 키,값으로 구성된 Entry객체 저장
많은 양의 데이터를 검색하는데 유용
HashTable
HashTable은 HashMap과 내부구조 동일.
.....내용이 삼천만개... 오늘 할 내용이 너무 많은데 아직도 이해를 다 못했다. 내일 당장 페어프로그래밍으로 문제들을 풀어야하는데 눈앞이 캄캄하다ㅜㅜ
사실 처음에 제네릭부터 이해하는데 한참 걸렸다.
이해가 아예 안되는걸 열심히 구글링하며 정보를 찾고 또 고민해보고 코드를 작성해보며 조금씩 이해하게된것같다.
컬렉션은 뭐... 손톱만 살짝 담군 느낌..?
오늘은 아무래도 밤을 새야할것같다.
아무리 어려운 내용이어도 코딩은 너무 재미써...!!!!!
너무 재밌기에 어려워도 포기하고싶은 마음은 눈꼽만큼도 들지 않는다. 열심히 잘 해봐야지!!!!