제네릭 (Generic) 이란
제네릭이란 클래스나 인터페이스 선언에 유형 매개변수가 들어있는 클래스를 뜻한다.
▶ 제네릭 타입은 클래스 또는 인터페이스 이름 뒤에 "< >" 부호가 붙고, 그 사이에 Parameter가 위치한다.
자바 5 버전부터 제네릭이 도입된 이후 클래스에 원치않는 데이터형이 들어가는 것을 방지 할 수 있다.
▶ 반대로 값을 가져올 때도 형 변환을 하지 않게 되었다.
제네릭은 형 안정성(Type Safety)를 위해 사용합니다.
제네릭이 없는 코드가 갖는 문제
▲ ABC Class에는 무엇이든지 담을 수 있다.
해당 타입에 맞춰 강제 형 변환을 해줘야 한다.
잘못 형 변환을 한다면 오류로 이어지는 결과가 된다.
제네릭의 등장 이후 문제 해결
<type> 키워드로 인해, 클래스에 저장되는 타입은 미정상태로 둔다.
값을 꺼낼 때 형변환을 하지 않는다.
NEW로 생성할 때 클래스를 다양한 형태로 만들어 사용이 가능하다.
ABC.class
public class ABC<T> {
// <타입> 처럼 사용함
private T t;
// alt + shift + s
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
Person.class
public class Person {
}
MainClass
public class MainClass {
public static void main(String[] args) {
// ABC abc = new ABC();
// abc.setT("홍길동");
// String을 저장하는 용도의 객체
ABC<String> abc = new ABC<String>();
abc.setT("홍길동");
String name = abc.getT();
System.out.println(name);
System.out.println("--------------------------");
// int로 저장하는 용도의 객체 (반드시 wrapper만 쓸 수 있어용)
ABC<Integer> abc2 = new ABC<Integer>();
abc2.setT(10);
int age = abc2.getT();
System.out.println(age);
System.out.println("---------------------------");
// Person 저장하는 용도의 객체 (뒤에 제네릭 생략이 가능)
ABC<Person> abc3 = new ABC<>();
abc3.setT(new Person());
Person p = abc3.getT();
}
}
제네릭(Generic)은 타입을 한 개 이상, 즉 두 개도 표기가 가능하다.
public class ABC<A, B> {
// 멀티제네릭 (A, B를 타입으로 사용)
private A key;
private B value;
public void setData(A key, B value) {
this.key = key;
this.value = value;
}
public B getValue(A key) {
return value;
}
}
public class MainClass {
public static void main(String[] args) {
ABC<Integer, String> abc = new ABC<>();
abc.setData(1, "홍길동");
String name = abc.getValue(1);
System.out.println(name);
}
}
Collection FrameWork
Collection
컬렉션은 배열과 유사하지만 데이터를 저장/조회/수정/삭제하는 작업을 쉽게 처리할 수 있다.
▶ 동적인 크기를 갖는다는 장점이 있다.
컬렉션은 데이터 적재 클래스 자료구조이다.
Collection의 종류
● Set
● List
● Map 등
▶ Collection은 위와 같은 Interface가 있으며 이를 구현한 클래스를 이용하면 객체들을 모음 저장할 수 있다.
컬렉션은 상속 구조를 띄는데, 아래 그림을 확인하면 이해하기에 편하다.
LIST
- List 컬렉션은 객체를 인덱스로 관리하기 때문에 객체를 저장하면 자동으로 인덱스번호가 부여되고
인덱스를 통해 객체를 검색, 삭제할 수 있는 기능을 제공한다. - List는 객체를 순서대로 저장하며 동일한 객체를 중복 저장할 수 있다.
LIST 주요 메서드
객체 추가 기능
● add(E e) : 객체를 list의 맨 끝부분에 추가
● add(int index, E e) : 인덱스에 객체를 추가
● set(int index, E e) : 인덱스에 저장된 객체를 주어진 객체로 변경
객체 검색 기능
● contains(Object o) : 객체가 저장되어있는 지 여부 판단
● get(int index) : 인덱스에 저장되어 있는 개체를 리턴
● isEmpty() : 컬렉션이 비어있는지의 여부를 판단
● size() : 저장되어 있는 전체 객체 수를 리턴
객체 삭제 기능
● clear() : 저장된 모든 객체를 삭제
● remove(int index) : 주어진 인덱스에 저장된 객체를 삭제
● remove(Object o) : 주어진 객체를 삭제
ArrayList
배열과 흡사하지만, 자동으로 사이즈를 조절한다.
ArrayList에 특정 인덱스의 객체를 제거하면 자동으로 바로 뒤 인덱스부터 마지막 인덱스까지 모두 앞으로 1당겨짐
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ArrayListEx01 {
public static void main(String[] args) {
// 밥 먹는 횟수보다 많이 사용됨
// ArrayList<String> list = new ArrayList<>();
List<String> list = new ArrayList<>();
// 값의 추가
list.add("Java");
list.add("Spring");
list.add("Database");
list.add("Js");
list.add("Docker");
System.out.println(list.toString());
// 크기 확인
System.out.println(list.size());
// 값을 중간에 추가
list.add(2, "이순신");
System.out.println(list.toString());
// 값을 한번에 추가
String[] arr = { "A", "B", "C" };
List<String> newList = Arrays.asList(arr);
list.addAll(newList);
System.out.println(list.toString());
// 값의 확인 get
// list[0] == list.get(0)
String x = list.get(0);
System.out.println(x);
System.out.println(list.toString()); // 리스트 길이는 변함 x
// 값의 삭제 remove(인덱스), remove(값)
list.remove(2);
System.out.println(list.toString());
list.remove("A"); // 가장 첫번째로 발견되는 A를 삭제
System.out.println(list.toString());
// 값의 수정 set
list.set(3, "홍길동");
System.out.println(list.toString());
// 포함여부 확인
if (list.contains("Java")) {
System.out.println("Java가 존재함");
}
// 전체삭제 clear
list.clear();
System.out.println(list.toString());
}
}
LinkedList
● ArrayList는 내부 배열에 객체를 저장하여 관리하지만, LinkedList는 인접 참조를 링크하여 체인처럼 관리
● LikedList는 특정 인덱스의 객체를 제거하면 앞 뒤 링크만 변경되고 나머지링크는 변경 x
▶ 빈번한 객체의 삭제와 삽입은 ArrayList보다 좋은 성능을 발
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class LinkedListEx {
public static void main(String[] args) {
// ArrayList와 사용방법 동일 //LinkedList는 List와 Que에 속해있어 둘 다 사용가능
LinkedList<String> list = new LinkedList<>(); // 둘다 사용가능 + LinkedList만의 기능도 가능
List<String> list1 = new LinkedList<>(); // List처럼 사용
Queue<String> list2 = new LinkedList<>(); // Que처럼 사용
// List의 기능들
// 값의추가
list.add("Spring");
list.add("Summer");
list.add("Fall");
list.add("Winter");
System.out.println(list.toString());
// LinkedList만의 기능, 앞의추가, 끝의추가
list.addFirst("A");
list.addLast("B");
System.out.println(list.toString());
// 값 찾기 get(index)
String x = list.get(0);
System.out.println(x);
// 값 삭제 remove(index)
list.remove(0); // index 번호로 삭제
list.remove(4); // index 번호로 삭제(앞의 remove가 반영된후 index 재반영하여 계산)
list.remove("Summer"); // 값을 넣어 삭제
System.out.println(list.toString());
// 값의 수정
list.set(1, "Autumn");
System.out.println(list.toString());
System.out.println("ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ");
// Que의 기능들
// offer, offerFirst 앞에서 뒤로 추가
list.offer("1");
list.offer("2");
System.out.println(list.toString());
// 앞에 삭제
// poll, pollFirst 앞에서부터 삭제
System.out.println(list.poll());
System.out.println(list.toString());
// 값만 확인 peek
System.out.println(list.peek());
System.out.println(list.toString());
}
}
Set
- Set 컬렉션은 저장 순서를 보장하지 않는다. → 객체의 중복 저장을 허용하지 않는다.
- 인덱스로 관리하지 않으며 들어갈 때의 순서와 나올 때의 순서가 다를 수 있다.
- 인덱스로 객체를 검색 기능이 없고 전체 객체를 대상 한 번씩 반복해서 객체의 값을 가져오는 반복자(Iterator) 제공
Iterator 인터페이스의 주요 메서드
● hasNext() : 가져올 객체가 있으면 true 리턴, 없으면 false 리턴
● next() : 컬렉션에서 하나의 객체를 가져옴
● remove() : set 컬렉션에서 객체를 제거
set 계열 컬렌션 주요 메서드
객체 추가 기능
● add ( E e ) : 주어진 객체 저장. 성공적으로 저장 시 true 리턴, 중복 객체 저장 시 false 리턴
객체 검색 기능
● contains(Object o) : 주어진 객체가 저장되어 있는지 여부를 판단
● isEmpty() : 컬렉션이 비어있는지 확인
● iterator() : 저장된 객체를 한번씩 가져오는 반복자 객체를 리턴
● size() : 저장되어 있는 전체 객체 수를 리턴
객체 삭제 기능
● clear() : 저장된 모든 객체 삭제
● remove(Object o) : 주어진 객체를 삭제
HashSet
● HashSet 클래스는 Set 인터페이스를 구현한 컬렉션이므로 저장된 객체의 순서와 중복을 허용하지 않는다.
● 순차적으로 데이터를 관리하는 것에 비하여 속도가 향상된다.
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSetEx01 {
public static void main(String[] args) {
// set객체 생성
Set<String> set = new HashSet<>();
// 값의 추가 add
set.add("java");
set.add("java"); // 중복 x
set.add("js");
set.add("python");
set.add("spring");
System.out.println(set.size());
System.out.println(set.toString()); // 순서 x
// 값이 포함되어 있는지 확인
if (set.contains("java")) {
System.out.println("java가 포함됨");
}
// 값을 얻을 때는 반복자(iterator) 개념을 사용해서 반복해야 합니다.
Iterator<String> iter = set.iterator();
while (iter.hasNext()) { // 다음이 있다면 true
System.out.println(iter.next());
}
System.out.println("----------------------------");
for (String s : set) {
System.out.println(s);
}
// 값의 삭제
set.remove("js");
System.out.println(set.toString());
}
}
TreeSet
● TreeSet은 Tree 구조 기반으로 생성된 클래스로 Set 기능에 자동정렬 기능을 갖는다.
import java.util.Set;
import java.util.TreeSet;
public class TreeSetEx01 {
public static void main(String[] args) {
// TreeSet = 정렬 된 셋
// 사용방법은 Hashset과 동일함
Set<String> set = new TreeSet<>();
set.add("홍길동");
set.add("홍길자");
set.add("짱구");
set.add("철수");
set.add("훈이");
set.add("유리");
System.out.println(set.toString());
// 나머지 기능은 HashSet과 동일함
}
}
MAP 계열
- Map 컬렌션은 키(Key) 와 값(Value) 으로 구성된 Entry 객체를 저장하는 구조를 가진다.
▶ 키는 중복저장될 수 없지만, 값은 중복 저장이 가능하다.
Map 계열 주요 메서드
객체 추가 기능
● put ( K key, V value ) : 주어진 키와 값을 추가, 정상적으로 저장되면 그 값(value)를 리턴
객체 검색 기능
● containsKey(Object Key) : 주어진 키가 있는지의 여부를 확인
● containsValue(Object value) : 주어진 값이 있는지의 여부를 확인
● get(Object key) : 주어진 키에 들어있는 값을 확인
● isEmpty() : 컬렉션이 비어있는지 확인
● size() : 저장된 키의 총 수를 리턴
● values() : 저장된 모든 값을 컬렉션에 담아서 리턴
● keySet() : 저장된 모든 키를 Set 객체에 담아서 리턴
● entrySet() : 키와 값의 쌍으로 구성된 모든 Entry 객체를 Set에 담아서 리턴
객체 삭제 기능
● clear() : 모든 Entry를 삭제
● remove(Object key) : 주어진 키와 일치하는 Entry 객체를 삭제
HashMap
● 구조는 HashSet과 거의 동일하다.
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
public class HashMapEx01 {
public static void main(String[] args) {
// <키에대한타입, 값에대한타입>
// HashMap<Integer, String> map = new HashMap<>();
Map<Integer, String> map = new HashMap<>();
// 값을 추가 put
// 키값은 고유해야 합니다.
map.put(1, "짱구");
map.put(2, "유리");
map.put(3, "훈이");
map.put(4, "철수");
map.put(5, "짱구");
map.put(6, "맹구");
System.out.println(map.size());
System.out.println(map.toString());
// 값의 수정 - 맵에 동일한 키를 이용해서 변경하면 됩니다.
map.put(5, "홍길동");
System.out.println(map.toString());
// 값을 얻기 get
String value = map.get(3); // 키
System.out.println("3번 키에대한 값:" + value);
// 값을 삭제 remove
map.remove(5); // 키
System.out.println(map.toString());
// 키 or 값의 포함여부
System.out.println(map.containsKey(3)); // 키가 있다면 true
System.out.println(map.containsValue("짱구")); // 값이 있다면 true
// 맵을 반복하는 방법
Set<Integer> set = map.keySet(); // 키를 set으로 뽑아서 반환
for (Integer i : set) {
System.out.println("키:" + i + ", 값:" + map.get(i));
}
System.out.println("-----------------------------------");
Set<Entry<Integer, String>> entry = map.entrySet();
for (Entry<Integer, String> e : entry) {
// 엔트리는 key, value에 대한 getter를 제공합니다.
System.out.println("키:" + e.getKey() + ", 값:" + e.getValue());
}
System.out.println("--------------------------------------------------");
}
}
TreeMap
● TreeSet과 구조 거의 동일
import java.util.Map.Entry;
import java.util.TreeMap;
public class TreeMapEx01 {
public static void main(String[] args) {
// TreeMap은 사용방법이 동일합니다.
// 키가 저장되는 구조가 이진탐색트리 를 이용해서 키를 저장합니다.
// 키가 오름차순정렬이 됩니다.
TreeMap<String, Object> map = new TreeMap<>();
map.put("짱구", "20세");
map.put("유리", "30세");
map.put("훈이", "30세");
map.put("맹구", "20세");
System.out.println(map.toString());
Object o = map.get("맹구");
System.out.println((String) o);
// 검색에 특화된 기능을 제공해줍니다.
Entry<String, Object> entry = map.higherEntry("유라"); // 유라
// 트리구조에서 한단계 더 높은 위치에 있는 키중에서 가장 작은값
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
}
728x90
'Programming > Java' 카테고리의 다른 글
[JAVA] 정규표현식 (0) | 2024.02.26 |
---|---|
[ JAVA ] 익명 객체와 람다식 (0) | 2024.02.26 |
[JAVA] API-IO (Input 스트림과 Output 스트림) (1) | 2023.12.06 |
[JAVA] API - java.util Package (0) | 2023.12.05 |
[JAVA] API ( java.lang package ) (0) | 2023.12.04 |