제너릭(Generic)
: 필드의 자료형(참조형)이 추상적인 경우 자료형 대신 사용될 식별자 - 미지정 자료형
- Java 자료형(참조형) 선언시 < > 기호에 제너릭 타입(식별자) 선언 (식별자는 자유롭게 선언하면 된다.)
- 자바에서 제네릭(generic)이란 데이터의 타입(data type)을 일반화한다(generalize)는 것을 의미한다.
형식) public class 클래스명<제네릭, 제네릭, ...>
→ < > 안에 제네릭 타입은 , 기호를 사용하여 나열 선언 가능
- 제너릭으로 전달받을 수 있는 Java 자료형을 상속 기능을 사용하여 제한하는것도 가능하다.
형식) public class 클래스명 <제네릭 extends 클래스> { }
→ 제네릭은 반드시 부모클래스를 상속받은 Java 자료형만 전달받아 사용이 가능
//제너릭으로 전달받을 수 있는 Java 자료형을 상속 기능을 사용하여 제한
public class Generic<T extends Number> {
//public class Generic<T> {//제네릭 클래스
private T field;
public Generic() {
// TODO Auto-generated constructor stub
}
public Generic(T field) {
super();
this.field = field;
}
public T getField() {
return field;
}
public void setField(T field) {
this.field = field;
}
}
제네릭 타입의 필드가 선언된 클래스로 객체를 생성하여 사용하는 프로그램
→ 제네릭 타입 대신 설정된 Java 자료형의 객체만 필드에 저장 가능 - 제한적인 객체만 저장할 수 있다
→ 필드값을 반환받아 명시적 객체 형변환 없이 사용 가능
public class GenericApp {
public static void main(String[] args) {
//제네릭 클래스를 사용할 경우 제네릭 타입 대신 사용될 Java 자료형을 전달하여 사용
// => 전달받은 Java 자료형을 제네릭 타입 대신 사용하여 필드 또는 메소드 완성
Generic<Integer> generic1 = new Generic<Integer>(); //필드의 자료형 : Integer
//Generic<Integer> generic1 = new Generic<>(); //생성자의 제네릭 타입의 자료형 생략 가능
//제네릭 타입 대신 사용될 Java 자료형과 동일한 자료형의 객체를 전달받아 필드값 변경
// => 제네릭 타입 대신 사용될 Java 자료형과 다른 자료형의 객체를 전달한 경우 에러 발생
generic1.setField(100); //오토박싱 : 정수값 >> Integer 객체
//generic1.setField(12.34); //오토박싱 : 정수값 >> Double 객체
Integer returnObject1 = generic1.getField();
System.out.println("필드값 = " + returnObject1); //오토언박싱 : Integer 객체 >> 정수값
//출력 결과: 필드값 = 100
System.out.println("==================================================================");
Generic<Double> generic2 = new Generic<Double>();
generic2.setField(12.34);
Double returnObject2 = generic2.getField();
System.out.println("필드값 = " + returnObject2); //오토언박싱 : Double 객체 >> 실수값
System.out.println("==================================================================");
/*
//제네릭 타입이 상속받지 못한 클래스를 사용할 경우 에러 발생
Generic<String> generic3 = new Generic<String>();
generic3.setField("홍길동");
String returnObject3 = generic3.getField();
System.out.println("필드값 = " + returnObject3);
*/
System.out.println("==================================================================");
}
}
콜렉션 클래스(Collection Class)
: 자료구조(Data Structure)를 사용하여 다수의 객체를 효율적으로 관리(추가,삭제,검색)하기 위한 기능을 제공하는 데이터 수집 클래스들을 표현
→ Collection 인터페이스(Set 인터페이스, List 인터페이스), Map 인터페이스 중 하나를 상속받아 작성된 클래스
Set 인터페이스
Set 인터페이스를 상속받은 콜렉션 클래스 - HashSet, TreeSet 등
→ 객체의 저장 순서가 없으며 메모리 주소와 객체에 저장된 값이 동일한 객체는 중복 저장이 불가능하다.
즉, Set 인터페이스는 중복되는 요소를 허용하지 않는다.
HashSet 객체에는 모든 자료형의 객체를 Object 타입으로 저장 가능하다.
public class SetApp {
public static void main(String[] args) {
HashSet set = new HashSet();
}
}
하지만 제네릭을 사용하지 않고 HashSet 클래스로 객체를 생성하는 것은 권장하지 않는다.
→ HashSet 객체에 저장된 객체를 반환받아 사용할 경우 반드시 명시적 객체 형변환을 사용해야 하기 때문이다. (문제점)
따라서 제네릭을 사용하여 HashSet 클래스로 객체를 생성하는것을 권장한다.
import java.util.HashSet;
public class SetApp {
public static void main(String[] args) {
HashSet<String> set = new HashSet<String>();
}
}
→ HashSet 클래스의 제네릭 타입에 전달된 클래스의 객체만 저장이 가능하다.
→ HashSet 객체에 저장된 객체는 명시적 객체 형변환 없이 사용이 가능하다.
또는, 참조변수를 클래스가 상속받은 인터페이스(부모)를 이용하여 선언하는 것을 가장 권장한다.
→ 참조변수에 인터페이스를 상속받은 모든 자식클래스의 객체 저장이 가능하기 때문
→ 클래스간의 결합도를 낮춰 유지보수의 효율성 증가
import java.util.HashSet;
import java.util.Set;
public class SetApp {
public static void main(String[] args) {
Set<String> set = new HashSet<String>(); //HashSet 객체 생성 >> set 참조변수에 저장
}
}
Set.add(E element) : Set 객체에 요소를 추가하는 메소드
- 요소(Element) : 콜렉션 클래스의 객체에 제네릭 타입으로 전달되어 저장된 객체
set.add("홍길동");
set.add("임꺽정");
set.add("전우치");
→ 순서 상관없이 저장, 메모리 한도 내에서 저장하고 싶은 만큼 저장 가능
메모리 주소와 객체에 저장된 값이 동일한 객체는 중복 저장되지 않는다
set.add("홍길동");
set.add("임꺽정");
set.add("전우치");
set.add("홍길동");
System.out.println("set = " + set); //set = [홍길동, 전우치, 임꺽정]
Set.toString() : Set 객체에 저장된 모든 요소값(객체)를 문자열로 변환하여 반환하는 메소드
System.out.println("set.toString() = " + set.toString()); //set.toString() = [홍길동, 전우치, 임꺽정]
System.out.println("set = " + set); //set = [홍길동, 전우치, 임꺽정]
Set.size() : Set 객체에 저장된 요소의 객체를 반환하는 메소드
System.out.println("요소의 갯수 = " + set.size()); //요소의 갯수 = 3
Set.remove() : 매개변수로 전달받은 객체와 동일한 요소를 Set 객체에서 삭제하는 메소드
set.remove("임꺽정");
System.out.println("set = " + set); //set = [홍길동, 전우치]
Set.iterator() : Set 객체에 저장된 요소를 반복 처리할 수 있는 Iterator 객체를 반환하는 메소드
Set 객체의 요소를 가져올 순 없지만, iterator 객체를 반환하는 메소드를 호출해 저장된 요소를 반복처리할 수 있다.
-Iterator 객체 : 콜렉션 클래스의 객체 요소를 반복 처리 위한 기능을 제공하는 객체
→ 반복 지시자 : 커서(Cursor)를 사용하여 콜렉션 객체의 요소를 반복 처리
Iterator<String> iterator = set.iterator();
Iterator 객체를 사용하여 Set 객체에 저장된 모든 요소에 대한 일괄처리를 할 수 있다.
Iterator.hasNext() : Iterator 객체로 처리 가능한 요소의 존재 유무를 반환하는 메소드 → false : 처리 요소 미존재, true : 처리 요소 존재
Iterator.next() : 커서 위치에 요소(객체)를 반환하는 메소드 → 커서 위치의 요소를 반환하고 커서는 다음 요소의 위치로 자동 이동
while(iterator.hasNext()) {
String str = iterator.next();
System.out.print(str+ " ");
}
//출력결과: 홍길동 전우치
하지만 이 방법은 요즘은 잘 쓰지 않는다.
향상된 for문을 사용하면 내부적으로 Iterator 객체를 사용하여 반복 처리가 가능하다.
for(String str : set) {
System.out.println(str + " ");
}
//출력결과: 홍길동 전우치
Set 인터페이스 이용해 로또프로그램 만들기
package xyz.itwill.util;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
//1~45 범위의 정수 난수값을 6개 제공받아 출력하는 프로그램 작성
// => 6개의 난수값은 서로 중복되지 않도록 작성하며 오름차순 정렬하여 출력
public class LottoSetApp {
public static void main(String[] args) {
//Integer 객체만 저장 가능한 Set 객체(HashSet 객체) 생성
Set<Integer> lottoSet = new HashSet<>();
Random random = new Random();
while(true) {
//1~45 범위의 난수값(Integer 객체)을 Set 객체의 요소로 저장
// => Set 객체에는 동일한 객체를 요소로 저장 불가
lottoSet.add(random.nextInt(45)+1);
//Set 객체에 저장된 요소의 갯수가 6인 경우 반복문 종료
if(lottoSet.size()==6) break;
}
//Set.toArray(E[] a) : Set 객체에 저장된 모든 요소값(객체)을 매개변수로 전달받은
//배열 요소에 저장하는 메소드 - Set 객체를 배열로 변환하는 메소드
Integer[] lotto = lottoSet.toArray(new Integer[0]); //배열의 형태만 전달하면 되기 때문에 []안의 숫자 중요X
//Arrays.sort(Object[] a) : 매개변수로 전달받은 배열의 요소값을 정렬하는 메소드
Arrays.sort(lotto); //배열의 요소들이 알아서 자동정렬 된다
//Arrays.toString(Object[] a) : 매개변수로 전달받은 배열의 모든 요소값을 문자열로
//변환하여 반환하는 메소드
System.out.println("행운의 숫자 = " + Arrays.toString(lotto));
}
}
List 인터페이스★
List 인터페이스를 상속받은 콜렉션 클래스 - ArrayList, Vector, LinkedList 등
→ 특징 : List 객체의 요소를 차례대로 저장 (순서 존재) - 첨자(Index)를 이용하여 요소를 구분하여 사용 가능
>> Index 이용해 원하는 요소를 제공받아 사용 가능
→ 단점 : List 객체에 저장된 요소를 검색하는 속도가 비효율적
ArrayList와 Vector는 같은 클래스이고 메소드도 같다.
다른점은, Vector는 메소드가 동기화처리 되어있고(synchronized) ArrayList는 동기화처리 되어있지 않다는 점이다.
Vector는 동기화 되어있기 때문에 다중스레드에서는 안전하지만 대신 속도가 느리다는 단점이 있다.
따라서 웹프로그램 만들 땐, 일반적으로 동기화가 필요 없고 (데이터베이스 자체가 이미 동기화 되어 있기 때문) 속도 때문에 ArrayList를 많이 쓴다.
LinkedList는 검색 속도가 좋진 않으나, 특정 인덱스에 객체를 추가하거나 제거하는 일이 빈번하다면 LinkedList를 사용하는 것이 좋다.
하지만 인덱스로 객체를 찾거나 맨 마지막에 객체를 추가하는 경우에는 ArryList의 성능이 더 좋다.
package xyz.itwill.util;
import java.util.ArrayList;
import java.util.List;
public class ListApp {
public static void main(String[] args) {
//참조변수를 클래스가 상속받은 인터페이스(부모)를 이용하여 선언
List<String> list=new ArrayList<String>();
}
}
List.add(E element) : List 객체에 요소를 추가하는 메소드
→ List 객체에 요소가 차례대로 저장
list.add("홍길동");
list.add("임꺽정");
list.add("전우치");
list.add("일지매");
List.toString() : List 객체에 저장된 모든 요소(객체)를 문자열로 변환하여 반환하는 메소드
//System.out.println("list.toString() = "+list.toString());
System.out.println("list = "+list); //list = [홍길동, 임꺽정, 전우치, 일지매]
List 객체는 동일한 객체를 요소로 저장이 가능하다
list.add("임꺽정");
System.out.println("list = "+list); //list = [홍길동, 임꺽정, 전우치, 일지매, 임꺽정]
List.size() : List 객체에 저장된 요소의 갯수를 반환하는 메소드
System.out.println("요소의 갯수 = "+list.size()); //요소의 갯수 = 5
List.get(int index) : List 객체에서 index 위치에 저장된 요소값(객체)을 반환하는 메소드
System.out.println("3번째 위치에 저장된 문자열 = "+list.get(2));
//3번째 위치에 저장된 문자열 = 전우치
>> Set에는 없는 메소드이다. List는 순서가 있기 때문에 해당 메소드가 존재한다.
List.add(int index, E element) : List 객체에서 index 위치에 요소를 삽입하는 메소드
list.add(4, "장길산");
System.out.println("list = "+list); //list = [홍길동, 임꺽정, 전우치, 일지매, 장길산, 임꺽정]
List.remove(E element) : 매개변수로 전달받은 객체와 동일한 요소를 List 객체에서 삭제하는 메소드 - 첫번째로 검색된 요소만 삭제
List.remove(int index) : List 객체에서 index 위치의 요소를 삭제하는 메소드 (List는 순서가 존재하기 때문에 해당 메소드를 더 많이 이용)
//list.remove("임꺽정");
list.remove(5);
System.out.println("list = "+list); //list = [홍길동, 임꺽정, 전우치, 일지매, 장길산]
List.set(int index, E element) : List 객체에서 index 위치의 요소값(객체)를 변경하는 메소드
list.set(1, "임걱정");
System.out.println("list = "+list); //list = [홍길동, 임걱정, 전우치, 일지매, 장길산]
List 객체에 저장된 모든 요소에 대한 일괄처리
//일반 for 구문 사용
for(int i=0;i<list.size();i++) {
System.out.print(list.get(i)+" ");
}
System.out.println();
//Iterator 객체 사용
//List.iterator() : List 객체에 저장된 요소를 반복 처리할 수 있는 Iterator 객체를 반환하는 메소드
Iterator<String> iterator=list.iterator();
while(iterator.hasNext()) {
System.out.print(iterator.next()+" ");
}
System.out.println();
//향상된 for 구문 사용
for(String str : list) {
System.out.print(str+" ");
}
System.out.println();
//출력 결과: 홍길동 임걱정 전우치 일지매 장길산
Collections.sort(List list) : 매개변수로 전달받은 List 객체의 요소를 정렬하는 메소드
-Collections 클래스 : List 객체의 요소를 관리하기 위한 기능의 메소드를 제공하는 클래스
Collections.sort(list);
System.out.println("list = "+list); //list = [일지매, 임걱정, 장길산, 전우치, 홍길동]
List.clear() : List 객체에 저장된 모든 요소를 삭제하여 초기화 처리하는 메소드
List.isEmpty() : List 객체에 요소가 저장되어 있는 경우 [false]를 반환하고 List 객체에 저장된 요소가 없는 경우 [true]를 반환하는 메소드
list.clear();
if(list.isEmpty()) {
System.out.println("List 객체에 저장된 요소가 하나도 없습니다.");
}
//List 객체에 저장된 요소가 하나도 없습니다.
Arrays.asList(E... element) : 매개변수로 전달받은 0개 이상의 요소값(객체)이 저장된 List 객체를 생성하여 반환하는 메소드
List<Integer> numberList=Arrays.asList(10,20,30,40,50);
System.out.println("numberList = "+numberList); //numberList = [10, 20, 30, 40, 50]
Map 인터페이스★
Map 인터페이스를 상속받은 콜렉션 클래스 - HashMap, Hashtable,Properties 등
→ 이름(Key)과 객체(Value)를 하나의 그룹으로 묶어 Map 객체에 저장하여 관리한다. (Key는 절대 중복되어선 안된다. 객체는 중복되어도 O)
→ 엔트리(Entry) : Map 객체에 이름과 객체를 하나로 묶어 저장하기 위한 단위
→ 이름을 이용하여 객체를 빠르게 검색하여 제공하기 위한 콜렉션 클래스 >> 원하는 객체를 키를 이용해 빠르게 찾아낼 수 있는 것이 장점이다.
검색속도를 빠르게 하기 위해 사용한 것이기 때문에 순서는 없다.
이름(K)과 저장 객체(V)에 대한 제네릭 타입 2개에 자료형을 전달하여 객체 생성
public class MapApp {
public static void main(String[] args) {
Map<String, String> map=new HashMap<String, String>();
}
}
Map.put(K key, V value) : Map 객체에 엔트리를 추가하는 메소드
→ Map 객체에 저장되는 엔트리의 이름(Key)을 Set 객체로 저장되므로 중복 저장 불가능
map.put("1000", "홍길동");
map.put("2000", "임꺽정");
map.put("3000", "전우치");
map.put("4000", "일지매");
map.put("5000", "장길산");
Map.toString() : Map 객체에 저장된 모든 엔트리를 문자열로 변환하여 반환하는 메소드
//System.out.println("map.toString() = "+map.toString());
System.out.println("map = "+map);
//map = {5000=장길산, 4000=일지매, 1000=홍길동, 2000=임꺽정, 3000=전우치}
Map.put(K key, V value) 메소드 호출시 이름(Key)이 중복된 경우 해당 이름의 엔트리의 객체(Value)를 변경하여 저장
map.put("2000", "임걱정");
System.out.println("map = "+map);
//map = {5000=장길산, 4000=일지매, 1000=홍길동, 2000=임걱정, 3000=전우치}
Map.remove(K key) : Map 객체에 저장된 엔트리에서 매개변수로 전달받은 이름(Key)에 대한 엔트리를 검색하여 삭제하는 메소드
map.remove("4000");
System.out.println("map = "+map);
//map = {5000=장길산, 1000=홍길동, 2000=임걱정, 3000=전우치}
Map.get(K key) : Map 객체에 저장된 엔트리에서 매개변수로 전달받은 이름(Key)에 대한 엔트리를 검색하여 엔트리의 객체를 반환하는 메소드
→ 이름(Key)에 대한 엔트리가 없는 경우 null 반환
String name=map.get("1000");
System.out.println("name = "+name); //name = 홍길동
Map.keySet() : Map 객체에 저장된 모든 엔트리의 이름(Key)을 Set 객체로 반환하는 메소드
Iterator<String> iteratorKey = map.keySet().iterator();
//Iterator.hasNext() : Iterator 객체로 처리 가능한 요소의 존재 유무를 반환하는 메소드
//→ false : 처리 요소 미존재, true : 처리 요소 존재
while(iteratorKey.hasNext()) {
//Iterator.next() : 커서 위치에 요소(객체)를 반환하는 메소드
//→ 커서 위치의 요소를 반환하고 커서는 다음 요소의 위치로 자동 이동
String key = iteratorKey.next();
String value = map.get(key);
System.out.println(key+" = "+value);
}
for(String key : map.keySet()) {
System.out.println(key+" = "+map.get(key));
}
//출력 결과(동일함)
//5000 = 장길산
//1000 = 홍길동
//2000 = 임걱정
//3000 = 전우치
Map.values() : Map 객체에 저장된 모든 엔트리의 객체(Value)을 Collection 객체(List 객체)로 반환하는 메소드
Iterator<String> iteratorValue = map.values().iterator();
while(iteratorValue.hasNext()) {
String value = iteratorValue.next();
System.out.println(value);
}
for(String value : map.values()) {
System.out.println(value);
}
//출력 결과(동일함)
//장길산
//홍길동
//임걱정
//전우치
'학원 > 복기' 카테고리의 다른 글
0424 - javax.swing 패키지 (0) | 2023.04.24 |
---|---|
0421 - 정규표현식, java.awt 패키지,이벤트 처리 프로그램 (0) | 2023.04.22 |
0419 - java.util 패키지 (Random, UUID, Date 클래스) / java.text 패키지 (SimpleDateFormat, DecimalFormat 클래스) (0) | 2023.04.19 |
0417 - StringBuffer 클래스,Wrapper 클래스, Integer 클래스 / 스레드, 다중스레드, 스레드 동기화 (0) | 2023.04.17 |
0414 - 예외전달, Java API, System클래스, String클래스 (0) | 2023.04.15 |