[JAVA] Generic, Collection Framework

zirryo·2022년 7월 14일
0

⚡️ STUDY

목록 보기
8/15
post-thumbnail
week 4 / 22.07.14

Generic

💿 제네릭

타입을 구체적으로 지정하지 않고, 추후에 지정할 수 있도록 일반화 해두는 것
작성한 클래스 혹은 메서드의 코드가 특정 데이터 타입에 얽매이지 않게 하는 것



  • 제네릭 클래스 : 제네릭이 사용된 클래스

    • 클래스 바디에서 타입 매개변수를 임의의 타입으로 사용가능.
    • 아래의 코드에서 T가 타입 매개변수, <T> 의 형태로 클래스 우측에 표기함.
    • 매개변수를 여러 개 사용할 경우 <K, V>의 형태로 나타냄.
    • 타입 매개변수는 임의의 문자로 지정가능하며, T, K, V, E, N, R 자주 사용.
      class Genclass<T> {   
      	private T item;
      
          public Genclass(T item) {
              this.item = item;
          }
      
          public T getItem() {
              return item;
          }
      
          public void setItem(T item) {
              this.item = item;
          }
      }
    • static 키워드가 붙은 변수, 즉 클래스 변수에는 타입 매개변수를 사용할 수 없음. (클래스 변수는 모든 인스턴스가 공유하는 변수인데 인스턴스 마다 다른 타입 매개변수를 사용할 경우 클래스 변수 값의 타입이 서로 달라 값을 공유할 수 없기 때문)


  • 제너릭 클래스 사용

    • 멤버를 구성하는 코드에 특정한 타입이 지정되지 않은 클래스이므로, 인스턴스화 할 때 클래스로 타입 지정을 해야 함.(기본 타입 지정 불가)

      
       Genclass<String>  gen1 = new Genclass<String>("use generic");
       Genclass<Integer> gen2 = new Genclass<Integer>(714);
       Genclass<Double>  gen3 = new Genclass<Double>(3.29);
      
       // 아래와 같이 <> 안에 타입을 생략해도 됨.
       Genclass<String>  gen4 = new Genclass<>("use generic");
       Genclass<Integer> gen5 = new Genclass<>(714);
       Genclass<Double>  gen6 = new Genclass<>(3.29);



  • 제한된 제네릭 클래스

    • 타입을 특정 클래스의 하위 클래스로 제한. extends 키워드 사용
      
      class Book { ... }
      class Novel extends Book { ... }
      class November { ... }
      
      class Paper<`T extends Book`> {
          private T bookmark;
      }
      
      public static void main(String[] args) {
         Paper<`Book`> book = new Paper<>();
         Paper<`Novel`> novel = new Paper<>();
         Paper<`November`> november = new Paper<>(); // 에러 발생
      }

    • 타입을 특정 인터페이스를 구현한 클래스로 제한. extends 키워드 사용
      
      interface Book { ... }
      class Novel implements Book { ... }
      class Mystery extends Novel { ... }
      
      class Paper<T extends Book> {
          private T bookmark;
      }
      
      public static void main(String[] args) {
         Paper<Book> book = new Paper<>();
         Paper<Novel> novel = new Paper<>();
         Paper<Mystery> november = new Paper<>(); 
         // Mystery의 상위 클래스 Novel이 Book을 구현했기 때문에 조건 만족
      }

    • 타입을 특정 클래스의 하위 클래스 & 특정 인터페이스를 구현한 클래스로 제한
      
      interface Book { ... }
      class Novel implements Book { ... }
      class Mystery extends Novel { ... }
      
      class Paper<T extends Novel & Book> { // 상속 클래스 & 인터페이스의 순서로 작성
          private T bookmark;
      }
      
      public static void main(String[] args) {
         Paper<Book> book = new Paper<>(); // 하위 클래스가 아니므로 에러 발생
         Paper<Novel> novel = new Paper<>();
         Paper<Mystery> november = new Paper<>(); 
         // Mystery의 상위 클래스 Novel이 Book을 구현했기 때문에 조건 만족
      }



  • 제너릭 메서드
    : 클래스 내부의 특정 메서드만 제네릭으로 선언하는 것.
    • 타입 매개변수 선언은 반환타입 앞에서 이루어지며, 메서드 내에서만 사용 가능함.
    • static 메서드에서도 사용 가능.
    • 메서드의 타입 매개변수는 제네릭 클래스의 타입 매개변수와 별개
      class TestMethod<T> {
      	// 제네릭 클래스의 타입 매개변수 T와	
      	public <T> void add(T element) {
      		// 제네릭 메서드의 타입 매개변수 T는 서로 다르다.
      	}
      }
      TestMethod<String> tm = new TestMethod<>(); // 클래스의 인스턴스화
       tm.<Integer>add(5); // 메서드 호출
       tm.add(2); // 타입 지정 생략
    • 제너릭 메서드를 정의하는 시점에는 어떤 타입이 입력될 지 알 수 없으므로, 특정 클래스의 메서드를 사용할 수 없다.
      ex) String의 length 메서드
    • 최상위 클래스인 Object 🔗 클래스의 메서드는 사용 할 수 있음.



💿 래퍼 클래스

Wrapper Class

  • 기본 타입의 변수를 객체로 다루어야 하는 경우에, wrapper class로 기본형 변수를 객체로 감싸서 사용함. 다음과 같은 경우가 있다.
  1. 매개변수가 객체로 요구될 때
  2. 기본형 값이 아닌 객체로 저장해야 할 때
  3. 객체 간의 비교가 필요할 때
  • 래퍼 클래스로 감싸고 있는 기본 타입 값은 외부에서 변경할 수 없으며, 변경하고 싶다면 새로운 포장 객체를 생성해야 함.
  • 래퍼 클래스는 equals()가 오버라이딩 되어있어 주소 값이 아닌 객체 내부의 값 비교 가능.
    기본 타입      래퍼 클래스
     byte        Byte
     char        Character
     int         Integer
     float       Float
     double      Double
     boolean     Boolean
     long        Long
     short       Short
  • Boxing & Unboxing
    • 박싱 : 기본 타입의 값을 포장 객체로 만드는 것.
    • 언박싱 : 포장 객체에서 기본 타입의 값을 얻는 것.
      Integer wrapInt = new Integer(3);   // 박싱
      int wrapint = wrapInt.intValue();   // 언박싱
      Float wrapFloat = new Float(5.5);   // 박싱
      float wrapfloat = wrapFloat.floatValue();   // 언박싱




Collection Framework

📀 컬렉션 프레임워크

컬렉션 : 여러 데이터들의 집합

컬렉션 프레임 워크

  • 컬렉션을 다루기 편리하게 하는 메서드들을 정의해놓은 것.

  • 자료구조에 데이터 추가, 삭제, 수정, 검색등을 가능하게 하는 메서드 제공.

  • 주요 인터페이스 : List, Set, Map

  • 컬렉션 인터페이스의 메서드

    기능리턴타입메소드기능
    객체 추가booleanadd(Object o)/
    addAll(Collection c)
    주어진 객체 및 컬렉션의 객체들을
    컬렉션에 추가
    객체 검색booleancontains(Object o)/
    sontainsAll(Collection c)
    주어진 객체 및 컬렉션이 저장되어
    있는지 여부를 리턴
    Iteratoriterator()컬렉션의 iterator를 리턴
    booleanequals(Object o)컬렉션이 동일한지 여부를 확인
    booleanisEmpty()컬렉션이 비어있는지 여부 확인
    intsize()저장되어 있는 전체 객체 수 리턴
    객체 삭제voidclear()컬렉션에 저장된 모든 객체를 삭제
    booleanremove(Object o)/
    removeAll(Collection c)
    주어진 객체 및 컬렉션 삭제,
    성공 여부 리턴
    booleanretainAll(Collection c)주어진 컬렉션을 제외한 모든 객체를
    컬렉션에서 삭제, 컬렉션에 변화가
    있는지의 여부를 리턴
    객체 변환Object[]toArray()컬렉션에 저장된 객체를
    객체배열(Object [])로 반환
    Object[]toArray(Object[] a)주어진 배열에 컬렉션의 객체를
    저장해서 반환

    🔗 markdown 테이블 제너레이터




📀 List< E >

데이터의 순서가 유지되며, 중복 저장이 가능한 컬렉션을 구현할 때 사용

List 인터페이스의 특징

  • 객체를 일렬로 늘어놓은 구조.
  • 객체를 인덱스로 관리하며, 자동으로 인덱스 부여됨.
  • 인덱스를 이용하여 객체 검색, 추가, 삭제 등이 가능함.
  • 컬렉션의 인터페이스를 상속 받아 사용 가능함.
  • List 인터페이스의 메서드
    기능리턴타입메소드기능
    객체
    추가
    voidadd(int index,
    Object element)
    주어진 인덱스에 객체 추가
    booleanaddAll(int index,
    Collection c)
    주어진 인덱스에 컬렉션을 추가
    Objectset(int index,
    Object element)
    주어진 위치에 객체 저장
    객체
    검색
    Objectget(int index)주어진 인덱스에 저장된 객체 반환
    intindexOf(Object o) /
    lastIndexOf(Object o)
    순방향 / 역방향으로 탐색하여
    주어진 객체의 위치 반환
    ListIterlatorlistIterator() /
    listIterator(int index)
    (List의 객체 탐색 /
    주어진 index부터 탐색)
    ListIterator 반환
    ListsubList(int fromIndex,
    int toIndex)
    fromIndex부터 toIndex에 있는
    객체를 반환
    객체
    삭제
    Objectremove(int index)주어진 인덱스에 저장된 객체 삭제
    & 삭제된 객체 반환
    booleanremove(Object o)주어진 객체 삭제
    객체
    정렬
    voidsort(Comparator c)주어진 비교자(comparator)로
    List 정렬



ArrayList
List의 인터페이스를 구현한 클래스, 컬렉션 프레임워크에서 가장 많이 사용됨.
기존의 Vector를 개선한 것.

  • 특징
    • 객체를 추가하면 객체가 인덱스로 관리됨.
    • 배열과 다르게 저장용량 초과시 자동으로 저장용량 증가.
    • 데이터가 연속적으로 존재함, 데이터의 순서 유지.
    • 저장할 객체 타입을 타입 매개변수로 표기하고 기본 생성자를 호출하여 생성.
    • 객체를 추가하면 0부터 인덱스 부여됨. 특정 객체를 제거하면, 앞으로 인덱스 1씩 당겨짐. 추가하면 인덱스 1씩 밀림.(속도 저하)
    • 데이터의 개수가 변하지 않는 경우에 사용하는 것이 효과적임.
    • 특정 인덱스의 주소값을 얻기 위해서 배열의 주소 + n * 데이터 타입의 크기 계산하여 빠른 접근 가능. 검색 유리함.
      
      List<타입 매개변수> 객체명 = new ArrayList<타입 매개변수>(초기 저장 용량);
      
      List<String> container1 = new ArrayList<String>();
      // String 타입의 객체를 저장하는 ArrayList 생성. 초기저장용량 defalut는 10. 
      
      List<String> container2 = new ArrayList<String>(30);
      // String 타입의 객체를 저장하는 ArrayList 생성. 초기저장용량 30. 




LinkedList
데이터를 효율적으로 추가, 삭제, 변경하기 위해 사용함.

  • 특징

    • LinkedList에는 데이터가 불연속적으로 존재하며, 데이터는 서로 연결되어 있음.
    • 각 요소(node)들은 자신과 연결된 이전 요소 및 다음 요소의 주소값과 데이터로 구성.
    • 데이터 삭제 : 삭제하고자 하는 요소의 이전 요소가 삭제하고자 하는 요소의 다음 요소를 참조하도록 변경. 데이터 복사 과정이 없으므로 처리속도 빠름.
    • 데이터 추가 : 삭제와 같은 메커니즘. 새로운 요소의 위치를 이전 요소와 다음 요소 사이에 연결. 처리속도 빠름
    • 데이터 검색 : 시작 인덱스부터 목표 인덱스까지 순차적으로 노드 접근하므로 검색 속도 느림.



Iterator
반복자. 컬렉션에 저장된 요소들을 순차적으로 읽어오는 역할.
컬렉션 인터페이스에는 Iterator 인터페이스를 구현한 클래스의 인스턴스를 반환하는 메서드인 iterator() 가 정의되어 있음.

  • Iterator 인터페이스의 메서드

    메서드기능
    hasNext()읽어올 객체가 남아 있으면 true, 없으면 false를 리턴
    next()컬렉션에서 하나의 객체를 읽음.
    next()를 호출하기 전, hasNext()를 통해 읽어올
    다음 요소가 있는지 먼저 확인
    remove()next()를 통해 읽어온 객체를 삭제.
    next()를 호출한 후, remove()를 호출해야 함





📀 Set< E >

요소의 중복을 허용하지 않고 저장 순서를 유지하지 않는 컬렉션

  • Set 인터페이스의 메서드
    기능리턴타입메소드기능
    객체 추가booleanadd(Object o)주어진 객체 추가, 성공하면 true,
    중복이면 false 리턴
    객체 검색booleancontains(Object o)주어진 객체가 Set에
    존재하는지 여부를 리턴
    booleanisEmpty()Set이 비어있는지 여부 확인
    Iteratoriterator()객체를 하나씩 읽어오는 반복자 리턴
    intsize()저장되어 있는 전체 객체 수 리턴
    객체 삭제voidclear()Set에 저장된 모든 객체를 삭제
    booleanremove(Object o)주어진 객체 삭제, 성공 여부 리턴




HashSet
Set 인터페이스를 구현한 가장 대표적인 컬렉션 클래스.

HashSet의 중복객체 판별법

  1. add(Object o) : 객체 저장.
  2. hashCode() : 메서드를 이용하여 저장하고자 하는 객체의 해시코드 & Set에 저장된 모든 객체의 해시코드 획득.
  3. 해시코드를 비교하여, 같은 해시코드가 있는지 판별.
    • 같은 해시코드 O : Set에 추가되지 않음. add(Object o) : false 리턴.
    • 같은 해시코드 X : Set에 객체 추가됨. add(Object o) : true 리턴.
  4. equals() : 메서드를 이용하여 객체 비교.
    • true : Set에 추가되지 않음. add(Object o) : false 리턴.
    • false : Set에 객체 추가됨. add(Object o) : true 리턴.




TreeSet
이진 탐색 트리의 형태로 데이터를 저장함.

이진 탐색 트리(Binary Search Tree)

  • 하나의 부모 노드가 최대 두 개의 자식 노드와 연결되는 이진 트리의 일종.
  • 정렬과 검색에 특화.
  • 모든 왼쪽 자식의 값이 루트나 부모보다 작고, 모든 오른쪽 자식의 값이 루트나 부모보다 큰 값을 가짐. (루트 == 최상위 노드)

  • TreeSet 클래스의 메서드
    메서드기능
    first()Set에 저장된 첫번째 값(가장 작은 값) 리턴
    last()Set에 저장된 마지막 값(가장 큰 값) 리턴
    higher(Element e)e 보다 큰 객체 중 가장 작은 객체 리턴, 없을 경우 null
    lower(Element e)e 보다 작은 객체 중 가장 큰 객체 리턴, 없을 경우 null
    subSet(E fromE,
    E toE)
    fromE와 크거나 같고, toE 보다 작은 객체의 집합 리턴
    headSet(Element e)e 보다 작은 객체의 집합 리턴
    tailSet(Element e)e 보다 크거나 같은 객체의 집합 리턴




📀 Map<K, V>

키와 값으로 구성된 객체를 저장하는 구조를 가짐
Entry 객체는 키와 값을 Key객체와 Value객체로 저장함.

Map 인터페이스의 특징

  • 모든 키는 고유한 값을 가짐.
  • 키가 다르면, 값이 같아도 다른 entry로 간주함.
  • 기존에 저장된 키와 새로운 값의 쌍이 추가될 경우 새로운 값으로 덮어씀.
  • 키와 값은 모두 객체이며, 기본타입일 수 없음.


  • Map 인터페이스의 메서드
    기능리턴타입메소드기능
    객체
    추가
    Objectput(Object key,
    Object value)
    주어진 객체 및 컬렉션의 객체들을
    컬렉션에 추가
    객체
    검색
    booleancontainsKey(Object key)주어진 키가 있으면 true,
    없으면 false를 리턴
    booleancontainsValue(Object key)주어진 값이 있으면 true,
    없으면 false를 리턴
    SetentrySet()모든 Map.Entry 객체를
    Set에 담아서 리턴
    Objectget(Object key)주어진 키에 해당하는 값을 리턴
    booleanisEmpty()컬렉션이 비어 있는지
    확인하여 리턴
    SetkeySet()모든 키를 Set 객체에 담아서 리턴
    intsize()저장된 Entry 객체의 총 개수 리턴
    Collectionvalues()저장된 모든 값을 컬렉션에
    담아서 리턴
    객체
    삭제
    voidclear()모든 Map.Entry(키, 값) 삭제
    Objectremove(Object key)주어진 key와 일치하는
    Map.Entry삭제,해당 값 리턴




HashMap
Map 인터페이스를 구현한 가장 대표적인 클래스.

특징

  • 해시 함수를 통해 '키'와 '값'이 저장되는 위치를 결정
  • 사용자는 그 위치를 알 수 없고, 삽입 순서와 위치는 관계가 없음.
  • Hashing을 사용하여 많은 양의 데이터를 검색하는 것에 강점을 가짐.
  • HashMap을 생성하는 방법은 아래와 같다.
    HashMap<String, Integer> hashmap = new HashMap<>();
  • 키와 값을 쌍으로 저장하기 때문에, iterator()를 직접 호출할 수 없음.
  • keySet() , entrySet() 메서드를 이용하여 Set 형태로 반환된 컬렉션에 iterator()를 호출하여 반복자를 만든 후, 반복자를 통해 순회할 수 있음.

🔗 HashMap의 다양한 메서드

0개의 댓글