본문 바로가기

학원/복기

0420 - 제너릭, Collection 클래스, Set 인터페이스, List 인터페이스, Map 인터페이스

제너릭(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);
	}
    
//출력 결과(동일함)
//장길산
//홍길동
//임걱정
//전우치