본문 바로가기
JAVA/기초

[JAVA 기초] 12 컬렉션 프레임워크 (1)

by 푸_푸 2022. 8. 18.
728x90

*제네릭(Generic)
- 제네릭 프로그래밍 : 어떤 값이 하나의 참조 자료형이 아닌 여러 참조 자료형을 사용할 수 있도록 프로그래밍하는 것
참조 자료형이 변환될 때 컴파일러가 검증하여 안정적

*제네릭의 필요성
여러 참조 자료형이 쓰일 수 있는 곳에 특정한 자료형을 지정하지 않고 클래스나 메서드를 정의한 후 사용하는 시점에 어떤 자료형을 사용할 것인지 지정하는 방식

*제네릭 클래스 정의하기

public class GenericPrinter<T>{
    private T material;
    
    public void setMeterial(T material) {
        this.material = material;
    }
    
    public T getMeterial(){
        return material;
    }
}


여러 자료형으로 바꾸어 사용할 material 변수의 자료형을 T라고 썼다. 이때 T를 자료형 매개변수라고 함
클래스 이름을 GenericPrinter<T>라고 정의하고 나중에 클래스를 사용할 때 T위치에 실제 사용할 자료형을 지정함
클래스의 각 메서드에서 해당 자료형이 필요한 부분에는 모두 T문자를 사용하여 구현함

*다이아몬드 연산자 <>

ArrayList<String> list = new ArrayList< > ();


선언된 자료형을 보고 생략된 부분을 컴파일러가 유추할 수 있기 때문에 생성 부분에서 생략 가능

*자료형 매개변수 T와 static
static 변수는 인스턴스 변수가 생성되기 이전에 생성됨. static 메서드에서는 인스턴스 변수를 사용할 수 없음
static 변수의 자료형이나 static 메서드 내부 변수의 자료형으로 T를 사용할 수 없음

T(type parameter)외에도 E(element), K(key), V(value)와 같은 다른 문자도 사용할 수 있음
A, B등 아무 문자나 사용해서 정의할 수 도 있음

*제네릭에서 자료형 추론하기

var list = new ArrayList<String>();


지역변수에 한해서 자료형을 추론할 수 있음

*제네릭 클래스 사용하기

GenericPrinter<Powder> powderPrinter = new GenericPrinter<powder>();
powderPrinter.setMeterial(new Powder( ));
Powder powder = powderPrinter.getMaterial( );    //명시적 형 변환을 하지 않음


- GenericPrinter<Power> : 제네릭 자료형, 매개변수화된 자료형
- powder : 대입된 자료형

*제네릭에서 대입된 자료형을 명시하지 않는 경우

GenericPrinter  powderPrinter2 = new GenericPrinter ( );    //컴파일 오류는 아니지만 경고 줄이 나타남
powderPrinter2.setMeterial(new Powder( ));
Powder powder = (Powder)powderPrinter2.getMaterial( );    //강제 형 변환해야 한다
GenericPrinter<Object> powderPrinter3 = new GenericPrinter<Object> ( );    
//여러 자료형을 동시에 사용하려면 Object 클래스 사용


*<T extends 클래스>
제너릭 클래스에서 T 자료형에 사용할 자료형에 제한을 둘 수 있음

*컬렉션 프레임워크에서 사용하는 제네릭
ArrayList.java 에서 ArrayList 클래스의 정의는 다음과 같음

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
    ...
}


배열은 요소를 가지므로 T보다는 Element를 뜻하는 E를 더 많이 사용함
다음과 같이 E 위치에 자료형을 넣어 배열을 사용함

ArrayList<String> list = new ArrayListM<String>( );


Array List 에서 미리 정의되어있는 메서드 중 가장 많이 사용하는 get() 메서드는 아래의 코드와 같음

public E get(int index){
    rangeCheck(index);
    return elementData(index);
}


E라고 쓰인 반환형은 ArrayList 를 생성할 때 사용한 자료형으로 반환함
또한, 컴파일러가 형 변환을 구현하므로 프로그래머가 직접 형 변환을 하지 않아도 됨

*컬렉션 프레임워크
자료 구조는 프로그램 실행 중 자료를 유지, 관리하기 위해 사용함
자료 구조를 미리 구현하여 java.util 패키지에 제공하는데 이를 컬렉션 프레임워크라고 함

*Collection 인터페이스
List 인터페이스와 Set 인터페이스가 있다
- List 인터페이스 : 순서가 있는 자료 관리, 중복 허용. ArrayList, Vector, LinkedList, Stack, Queue
- set 인터페이스 : 순서가 정해져 있지 않음, 중복을 허용하지 않음. HashSet, TressSet

- Collection 메서드
boolean add(E e) : Collection에 객체 추가
void Clear() : Collection의 모든 객체 제거
Iterator<E> iterator : Collection을 순환할 반복자를 반환
boolean remove(Object o) : Collection에 매개변수에 해당하는 인스턴스가 존재하면 제거
int size() : Collection에 있는 요소의 개수를 반환

*Map 인터페이스
하나가 아닌 쌍으로 되어있는 자료를 관리하는 메서드
key-value쌍. 키값은 중복될 수 없음. value 값은 여러 개일 수도 있고 중복 가능

- Map 메서드
V put(K key, V value) : key에 해당하는 value값을 map에 넣음
V get(K key) : key에 해당하는 value 값을 반환
boolean isEmpty() : Map이 비었는지 여부를 반환
boolean containskey(Object key) : Map에 해당 key가 있는지 여부를 반환
boolean containsValue(Object Value) : Map에 해당 value가 있는지 여부를 반환
Set keyset() : key 집합을 Set으로 반환(중복 불가)
Collection value() : value를 Collection으로 반환(중복 무관)
V remove(key) : key가 있는 경우 삭제
boolean remove(Object key, Object value) : key가 있는 경우 key에 해당하는 value가 매개변수와 일치할 때 삭제

*ArrayList 클래스
import java.util.ArrayList 를 선언해 주어야 함

*ArrayList와 Vector
ArrayList와 Vector의 가장 큰 차이는 동기화 지원 여부
동기화 : 두개 이상의 스레드가 Vector를 사용할 때 오류가 나지 않도록 실행 순서를 보장하는 것

-스레드와 멀티스레드 프로그래밍
스레드(=작업 단위)가 하나만 수행되면 단일 스레드 두 개 이상의 스레드가 동시에 실행되면 멀티스레드라고 함
두 개 이상의 스레드가 동시에 실행되면 같은 메모리 공간에 접근하기 때문에 변수 값이나 메모리 상태에 오류가 생길 수 있음
이때 메모리에 동시에 접근하지 못하도록 순서를 맞추는 것이 동기화
멀티스레드 환경이 아닌 경우 ArrayList를 사용하도록 권장하지만 사용하다가 동기화가 필요하다면 Vector로 바꾸지 않고

Collections.SynchronizedList(new ArrayList<String>( ));


이와 같이 ArrayList 생성 코드를 쓰면 됨

*LinkedList 클래스
배열은 생성할 때 정적 크기로 선언하고 중간에 자료를 삽입하거나 삭제할 때 나머지 자료를 이동시켜 빈 공간을 만들지 않고 연속된 자료 구조를 구현함
또한 처음 선언한 배열 크기 이상으로 요소가 추가되는 경우헤는 크기가 더 큰 배열을 새로 생성하여 각 요소를 복사해야 하는 번거로움이 있음
이런 점을 개선한 자료구조를 링크드 리스트라고 함
- 링크드 리스트 구조 : 각 요소는 다음 요소를 가리키는 주소값을 가짐
링크드 리스트는 자료를 중간에 추가하거나 삭제할 때 자료의 이동이 적고 편리
자로의 변동이 많은 경우에는 링크드 리스트, 자료의 변동이 없는 경우에는 배열을 사용하는 것이 효율적

*ArrayList로 스택과 큐 구현하기
- 스택 : 나중에 추가된 데이터를 먼저 꺼내는 LIFO 방식
- 큐 : 먼저 추가된 데이터부터 꺼내서 사용하는 FIFO 방식

*Collection요소를 순회하는 Iterator
순서가 없는 클래스에서 사용
boolean hashNext() : 이후에 요소가 더 있는지를 체크하는 메서드. 요소가 있다면 true를 반환
E next() : 다음에 있는 요소를 반환

728x90

댓글