ABOUT ME

Today
Yesterday
Total
  • 컬렉션 정리
    java 2021. 5. 10. 15:29

    배경

    사실 각 컬렉션의 특징 및 사용법은 익숙하다 못해 손이 먼저 반응한다. 다만, 하는 것과 아는 건 다르고 또 그걸 입 밖으로 말하는 건 다른 문제니 깔끔하게 정리하고자 한다. 각 컬렉션의 구체적인 특징이나 사용법보다는 java.util의 구조와 낯선 인터페이스 위주로 정리한다.

     

     

    ArrayList

    add()

    배열의 크기를 동적으로 변경하는 건 불가능하다. 리스트에 객체를 추가했을 때 capacity를 초과한 경우 grow()를 호출해 기존 배열을 복사하고 capacity를 1 추가한 새로운 배열을 얻는다. 리스트 생성 시 capacity의 값을 초기화하지 않으면 기본으로 10의 capacity가 할당된다. 애플리케이션의 성능을 고려한다면 넉넉한 capacity로 리스트를 선언하는 게 좋다.

     

    remove()

    ArrayList 기본 구현이 배열로 되어 있어 특정 위치의 객체를 삭제하는 작업은 비용이 많이 든다.

    단, 마지막 위치의 객체를 지우는 작업은 추가적인 작업이 필요 없게 설계했다.

     

    LinkedList는 내부적으로 이중연결리스트로 구성되어 있다는 점만 알면 될 것 같다.

     

     

    Stack

    본인은 웹서버를 만들면서 스택을 사용한 경우가 거의 없다.(필요한 상황이 없었다) 반면 알고리즘을 풀 때는 스택을 굉장히 자주 사용하고 아무 생각 없이 컬렉션에서 Stack를 사용했다. 사실 알고리즘을 풀 때 동시성을 제어해주는 코드가 문제 자체의 timeout과는 관련이 없는 경우가 대부분이다. 하지만 연산을 할 때 성능을 저하시키는 건 분명하다. Stack은 동시성을 제어하는 컬렉션인 Vector기반으로 구현되어 있는 클래스다.

     

    또한 스택 고유의 연산인 push pop과 같은 연산 모두 Vector의 메서드를 이용한 연산이다. 즉, 사실상 deprecated됐어야 할 클래스이며 사용을 지양해야 한다.

     

     

    Queue

    구현체로 사용할 수 있는 LinkedList와 ArrayDeque 모두 순서를 갖고 있다. 때문에 Deque타입으로 두 구현체 중 적절한 걸 골라 사용하면 된다. 스택을 사용하고 싶어도 마찬가지다. Deque는 또한 push()와 pop()처럼 스택직관적인 메서드도 제공한다. 다만, Queue는 만들었으면서 Stack은 인터페이스로 따로 안 뺀건 왜일까...

    Deque는 내부적으로 Queue를 상송받아서 스택으로만 사용하기엔 직관성이 떨어진다... 어쨌든 어떤 구현체를 사용할지는 시스템을 잘 생각해서 결정하면 될 것 같다.

     

    Iterator

    반복을 쉽게 다루기 위한 인터페이스다. 내부클래스를 정의해 현재 컬렉션 정보를 포함한 Iterrator를 반환할 수 있다. 문법적으로 크게 어려운 부분은 없다. 하나 주의해보면 remove() 메서드가 있는데 가장 최근에 읽은 객체를 삭제하는 메서드다. 다만, Iterator를 사용한 적도 드물 뿐더러 내 개념상 Iterator으로 컬렉션에 변화를 주는 건 그닥?

     

     

    Arrays

    배열의 연산과 관련된 static메서드를 주로 제공한다.

     

    fill() : 배열을 특정 값으로 채운다. 내부 구현 또한 단순하다.

    setAll() : 람다 이용해 값을 활용한 set을 할 수 있다.

     

    HashSet

    내부적으로 HashMap으로 구현되어 있다. 그냥 add할 때 map.put()하는 것과 똑같다. 다만, HashSet은 key값이 주로 객체이므로 몇가지 메서드는 주의해서 사용할 필요가 있다.

     

    - hashCode()값 재정의 : 두 객체를 동일한 객체로 여겨 중복삽입을 막으려면 hashCode()를 재정의해야 한다. HashMap에서 해시값을 구하는 건 hashCode()를 이용하기 때문이다.

    - equals() 재정의 : 두 객체가 같은지 판별하는 건 equals()이기 때문에 기본 equals()를 사용하면 주소를 이용해 비교한다. 오버라이딩해주자.

     

    LinkedHashSet은 내부적으로 저장순서까지 기억해줘서 순서대로 반복할 때 편리하다. 근데 set쓰면서 순서를 기억할 필요가 있었나싶다.

     

    'java' 카테고리의 다른 글

    Thread 정리  (0) 2021.05.11
    애너테이션 정리  (0) 2021.05.11
    Java Garbage Collector  (0) 2021.05.10
    BeanUtils copyProperties 사용법 및 주의사항  (0) 2021.05.04
    java 실행과정  (0) 2021.05.01

    댓글

Designed by Tistory.