한 걸음 두 걸음

자바 JAVA] 제네릭 Generic /컬렉션 Collection 본문

Language/Java

자바 JAVA] 제네릭 Generic /컬렉션 Collection

언제나 변함없이 2019. 11. 21. 20:45
반응형

제네릭 클래스란?

ArrayList가 있다면, 이는 String만 적용시킬 수 있는 것이 아니라, 여러 타입(String, 객체, Integer 등)을 적용시켜 재사용할 수 있도록 해주는 것입니다. 단, 기본타입(int, char, double 등의 Primitive data type은 지원하지 않습니다.) 이 때 타입을 나타내는 매개변수는 <>로 표기해야 합니다. <T1, T2, T3> , 타입매개변수

ArrayList<T>  //T타입을 element로 가지는 ArrayList클래스, 

다양한 타입에서도 동작하는 함수와 클래스 작성에 용이하게 쓰입니다.

class ClassName<K,V>{
    private K key;
    private V value;

    public ClassName(K k, V v){
        key = k;
        value = v;
    }
    public K getKey(){
        return key;
    }
}

이는 위처럼 반환값, 파라미터 등으로 교체되어 객체가 생성됩니다. K와 V는 클래스 내부에서 유일한 이름이어야하며, JAVA에서 타입의 이름은 대문자 1개로 짓기로 약속했습니다. 자주 쓰이는 이름과 뜻을 모아보자면

E = element
K = key
N = number
T = type
V = value
S = sub

사용예시

ClassName<String, Integer> c = new ClassName<>("예시",1); //int값을 넣었지만, auto boxing때문에 Integer로 변환되어 갑니다. 

만약 제네릭 표시를 안하고 호출하는 경우 (Raw)

ClassNam c = new ClassName<>("예시",1); 

두 매개변수는 Object에 담긴다.


인터페이스에도 제네릭이 사용된다.

public interface InterfaceName<K, V>{
    ...
}

제네릭 메소드

제네릭을 사용한 함수를 살펴볼까요? 타입을 매개변수로 받기도 합니다 : )
이는 일반 클래스 내부에도 들어갈 수 있고, 제네릭 클래스 내부에서도 사용됩니다. 이 때, 함수에서 사용되는 자료형을 명시적으로 적어줄 수도<String>, 생략할 수도 있습니다.

Arrays.swap( ... );
Arrays.<String>swap( ... );

어떤 타임의 자료든 swap시켜주는 함수

class Arrays{
    public static <T> void swap(T[] arr, int i, int j){
        T t = arr[i];
        arr[i] = arr[j];
        arr[i] = t;

    }
}

타입 매개변수를 제한하기

와일드카드를 사용하면 메소드의 매개변수나 리턴타입을 제한해줄 수 있습니다.

  1. A나 A의 자식클래스만 받기 혹은 A인터페이스를 구현한 객체만 받기

    public void print(ArratList< ? extends A> arr){
     ...
    }
  2. A나 A의 부모클래스 객체만 받기

    public void print(ArratList< ? super A> arr){
     ...
    }

    와일드카드?를 이용하여 타입을 가변성있게 받을 수 있습니다.

  3. 모두 받기

    public void print(ArratList<?> arr){
     ...
    }

    1, 2번 예시는 와일드카드와 상속관계를 함께 사용하여 해당 상속을 받은 객체 혹은 부모 객체로 제한하여 받을 수 있음을 표현했지만,
    3번은 무슨 객체든 다 받을 수 있음을 나타낸 것입니다.

만약 public void print(ArratList<Object> arr)이면 ArrayList<Object>만 다룰 수 있고 ArrayList<Integer>ArrayList<Double>등을 받지 못하는데, public void print(ArratList<?> arr)이면 ArrayList<Integer>ArrayList<Double>도 다 받을 수 있습니다.

Collection

컬렉션이란 자료구조 및 알고리즘을 제네릭 형식으로 제공하는 프레임워크입니다. java.util 패키지에 포함되어 있습니다.


계층 구조는 위와 같습니다.

컬렉션은 제네릭을 지원하는데 제네릭은 Primitive data type 변수 타입인 int, double 등을 지원하지 않기 때문에 Wrapper클래스를 사용하여 int대신 Integer, double 대신 Double 등으로 바꾸어 사용합니다.

Collection 또한 클래스로 구현되어 있으므로 계층적이며 기본적으로 Collection인터페이스를 상속받으므로,

int size()
boolean isEmpty()
boolean contains(Object o) o포함여부
boolean add( E e)
boolean remove(Object o)
Iterator<E> iterater();
addAll(Collection< ?extends E> c
containsAll, removeAll, clear, toArray
등의 함수를 지원합니다.

1. ArrayList

리스트는 인덱스로 데이터를 관리하며 중복된 값도 저장될 수 있습니다.
ArrayList는 배열의 크기가 고정되지 않고 동적으로 변화합니다. 하지만 데이터가 연속되게 저장되기 때문에 데이터 삽입 및 삭제에 대한 복잡도가 높습니다.(삽입 및 삭제 인덱스를 지정할 수 있어 편하긴 합니다.)

2. LinkedList

이러한 복잡도 문제를 해결할 수 있는 LinkedList이지만 ArrayList보다 덜 쓰입니다. 최적화할 때 사용하면 좋습니다. ArrayList보다 데이터를 참조하기 어렵습니다.

그러니 삽입과 삭제가 많은 데이터는 LinkedList를 사용하는 것이 용이합니다.

3. HashSet

Set<Integer> s = new HashSet();
s.add(1);
s.add(2);

순서를 고려하지 않기 때문에 중복 여부를 검사할 때 많이 사용합니다. 해쉬테이블을 이용한 Set이기 때문에 성능이 우수합니다. 

4. TreeSet

Red black Tree로 구현된 set이기 때문에 값에 따라 정렬되며 순서를 고려한 set을 사용할 때 사용합니다.  참고로 LinkedHashSet은 해쉬테이블과 연결리스트를 결합하여 워소들의 순서가 삽입 순으로 이뤄집니다. 

5. HashMap

키와 값의 Pair로 이루어진 자료구조로, https://onepinetwopine.tistory.com/477 를 참고해주세요.
순서가 중요하지 않은 경우 빠르게 찾을 수 있는 해쉬맵을 사용합니다.

6. TreeMap

순서 및 정렬이 필요할 때 트리맵을 사용합니다.

그 외에도 Stack, Queue 등의 컬렉션이 있습니다.

 

반응형