제너릭을 이용하는 대표적인 사례 >> Collection Framework
컬렉션이란?
: 여러 개의 요소를 묶어 하나의 단위로 만드는 객체이다. (=자료구조)
- 인터페이스 : 추상 클래스
- 구현 : 구체클래스
- 알고리즘 : 함수의 집합
컬렉션 프레임워크가 필요한 이유
: 모든 SW는 데이터를 여러 개 모아서 관리하는 기능을 포함한다. (CRUD, Create/Read/Update/Delete)
리스트, 큐, 집합, 맵과 같은 형태로 제공할 수 있는데, 재사용 가능성이 크므로 라이브러리로 제공한다.
-> 다양한 자료구조의 코드 간에 중복 제거(재사용의 최대화)
// 우리가 여태 사용해 왔던 ArrayList 또한 컬렉션 프레임워크에 해당한다.
자바의 컬렉션 프레임워크 장점
1) 계층적 인터페이스 사용
- 기능만 먼저 정의(상속 구조)
- 공통된 기능은 슈퍼 클래스로 선언
- 상위 인터페이스 메소드는 공통으로 사용할 수 있도록 정의
2) 인터페이스를 구현한 구체 클래스 제공
3) 알고리즘
- 정렬, 검색, 뒤집기, 복사, 섞기 등의 공통적인 유형을 알고리즘으로 제공한다.
코어 콜렉션 인터페이스
- 계층 구조를 통해 공통부를 슈퍼로 올리고 구체화되는 상속 구조를 가진다.
- 크게 컬렉션과 맵으로 나눠지고, 각 인터페이스에 대해 구체 클래스가 정의된다.
① Collection <Interface>
: 가장 상위의 클래스
(메소드 종류)
- int size()
- boolean isEmpty()
- boolean contains(Object element)
- boolean add(E element)
- boolean remove(Object element)
- Iterator <E> iterator()
(기능)
- 참조 다형성 : 참조 타입으로 이용
Collection<String> c = null;
c = new ArrayList<String>(); // 제너릭의 요소 타입은 동일해야한다.
c = new HashSet<String>();
- 변환 생성자 : 모든 컬렉션 c에서 다른 구체 타입으로 변환 가능
List<String> list = new ArrayList<>()(c);
- 벌크 연산 : containsAll(), addAll(), removeAll(), retainAll(), clear()
// 여러 개를 한번에 처리하는 메소드(true와 false 반환)
② Set <Interface>
: Collection과 비교하여, 중복된 요소를 제외하고, 객체를 추가 기능을 가진다.
(구체 클래스 구현)
- HashSet : 가장 기본적인 집합 구현 클래스, 순서가 없다.(랜덤한 것처럼 보임)
- TreeSet : 정렬한 집합
- LinkedHashSet : 들어간 순서를 유지하는 집합
(메소드 종류)
- add()
- addAll() : 합집합
- retainAll() : 교집합
- removeAll() : 차집합
(예제)
Set<Integer> randSet = new HashSet<>();
Collection<Integer> c = new ArrayList<>();
int n=0;
for(int i=0; i<30; i++){
n = rand.nextInt(30);
randSet.add(n); // randSet - 난수집합(중복 X)
c.add(i); // c - 제외집합
}
c.removeAll(randSet);
③ List <Interface>
: 콜렉션과 비교하여 위치 기반으로 접근할 수 있다.
(구체 클래스 구현)
- ArrayList : 배열 형식, 가장 많이 쓰이는 자료구조 (+성능이 가장 좋음)
- Vector : 배열 형태, 동기화, 스레드 안전 (+성능이 arraylist보다 떨어짐)
- LinkedList : 연결리스트 방식, 요소 중간에 추가/삭제할 경우 효율적이다.
- Stack : Vector를 상속, push/pop 기능 제공
(메소드 종류)
- 접근 : get, set, add, remove
- 검색 : indexOf, lastIndexOf
- 벌크 연산 : boolean addAll(int indx, Collection <T> c)
(예제)
public static <E> void swap(List<E> a, int i, int j){ // 제너릭 함수
E tmp = a.get(i);
a.set(i, a.getIj);
a.set(j, tmp);
}
public static void shuffle(List<?> list, Random rnd){
for(int i=list.size(); i>1; i--)
swap(list, i-1, nrd.nextInt(i));
}
두 번째 예제에서 <?>에 무엇이 나오든 간에 list의 자료형으로 컴파일되기 때문에 swap 함수를 사용할 때 list의 자료형을 따로 써주지 않아도 처음에 list에 선언된 자료형으로 알아서 변환하도록 한다.
④ Map <Interface>
: 키를 알면 바로 값을 꺼낼 수 있는 자료구조로써, 해시를 구현한 것이다.
(구체 클래스)
- HashMap : 기본 해시 맵 구현, 가장 효율적이다.
- TreeMap : 키에 대한 정렬
- LinkedHashMap : 들어간 순서 유지
(메소드)
- 기본 연산 : put, get, containsKey, containsValue, size, isEmpty
- 벌크 연산 : pubAll, clear
- 컬렉션뷰 연산 : 키나 값들의 뷰 제공
(예제)
HashMap<Integer, Student> stMap = new HashMap<>(); // HashMap<키, 값>
for(Student st: stList)
stMap.put(st.id, st); // 학번으로 학생을 넣어두겠다.
int id = s.nextInt();
Student st1 = stMap.get(id);
public class Freq{ // 빈도조사
public static void main(String[] args){
Map<String, Integer> m = new HashMap<String, Integer>(); // MAP<글자, 횟수>
for(String a: args){
Integer freq = m.get(a);
m.put(a, (freq == null)? 1: freq+1);
}
// m.size는 단어 개수
}
}
(컬렉션 뷰)
: 맵에서 집합 객체를 돌려받는 방법
// Map은 Collection Interface를 상속하지 않기 때문에 모든 값을 가져오기 어렵다. 따라서 맵에서 컬렉션 형태(집합 객체)로 바꿔 컬렉션처럼 접근 가능하도록 한다.
// 컬렉션 뷰에서 요소를 삭제하면 맵에서도 삭제된다, 컬렉션 뷰에서 추가는 불가능하다.
- keySet : Map의 키 Set을 나타냄
- values : Map의 값 Collection을 나타냄, 중복 포함
- entrySet : Map의 키-값 쌍을 포함한 Set을 나타냄
for(Map.Entry<KeyType, ValType> e: m.entrySet())
System.out.println(e.getKey() + : e.getValue());
'Computer Science > JAVA' 카테고리의 다른 글
[JAVA] 제너릭과 List (0) | 2020.11.20 |
---|---|
[JAVA] 기본 클래스, Object (0) | 2020.11.20 |
[JAVA] 제너릭이란? (0) | 2020.11.03 |
[JAVA] 추상화란? (0) | 2020.10.23 |
[JAVA] 인터페이스란? (+서점 구현하기) (0) | 2020.10.06 |
댓글