[F-Lab 모각코 챌린지] 1일차 - 클래스 로더와 해시테이블, 해시맵

[F-Lab 모각코 챌린지] 1일차 - 클래스 로더와 해시테이블, 해시맵 클래스로더에 대한 키워드와 간단한 정리, 해시 테이블 정리, 해시 테이블과 해시 맵의 차이를 간단히 정리하였습니다.

클래스로더

Loading: 로드

클래스 파일을 로드하여 JVM 의 Method area 에 올림

Linking: 링크

  • Verification: 검증
    읽어들인 클래스가 명세에 맞게 잘 구성되어있는지 검사 (제일 오래 걸리는 단계)
  • Preparation: 준비
    클래스가 필요로 하는 메모리를 할당 & 클래스의 필드 메서드 인터페이스를 나타내는 구조를 준비
  • Resolution: 해결
    심볼릭 메모리 참조를 실제 메모리 참조로 변경함
    클래스 상수 풀 내 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경

Initialization: 초기화

클래스 변수를 해당하는 초기 값으로 초기화 함

이 초기화 단계에서 static block 이 실행 될 수 있음.

클래스로더 특징

  • 계층 구조
    JVM 은 클래스 로더를 계층 구조로 관리함.
    부모 클래스 로더로 부터 클래스를 로드 할 수 있으며 이를 통해 클래스 간의 종속성과 공유 리소스의 관리가 가능해짐.
  • Dynamic Loading: 동적 로딩
  • Dynamic Linking: 동적 링크

해시테이블

  • 효율적인 데이터 검색을 위해 만들어짐
  • key / value 매핑을 이용하여
  • 해시 함수를 사용하여 키를 해시코드로 변환, 배열의 인덱스에 매핑하여 값을 저장함

장점

  • 검색 및 조회: 언제나 O(1) 의 탐색/읽기 속도를 가진다.
  • 고유한 값 유지: 중복된 키 불가능

특징

  • 로드 팩터(Load factor): 기본 값 0.75(해시 테이블이 75%이상 찼을 때 크기 조정) 이며 생성자를 통해 생성 할 때 변경 가능.
  • 버킷 (buckets): 해시테이블 내부에서 실제 데이터를 저장하기 위한 배열
  • 해시코드
  • 해시 함수
  • 해시 충돌: 서로 다른 키가 같은 해시 코드를 생성하는 문제
    해결 방법
    * Chaining: 체이닝
    * Open addressing: 개방 주소법
       * 리니어 프로빈
       * 쿼드라틱 프로빈
       * 더블 해싱

의문점

해시 함수는 일반적으로 큰 범위의 숫자를 리턴함. 해시 테이블의 내부가 배열로 되어있다면 가용하는 공간보다 큰 공간을 사용해야 할텐데 왜 O(1) 시간복잡도를 가짐?

answer:
해시 함수를 이용하여 인덱스 접근. 이 때 시간 복잡도는 O(1) 이 됨
해시 함수는 모듈로(Modulo: %) 연산을 통해 기본적으로 큰 범위의 해시값을 특정 인덱스로 접근 할 수 있도록 함. 때문에 일반적인 hashcode() 메서드에 비해 해시 충돌이 자주 일어날 수 있음.


해시 테이블과 해시맵 차이

공통 개념

키의 해싱(Hashing) 결과를 활용하여 값을 저장하고 조회하고, 키-값 쌍의 개수에 따라 동적으로 증가하는 연관 배열(Associate array) 이다.
  • Associate array: 연관 배열?
    * 자료구조 중 하나
    * 키 하나와 값 하나가 연관되어 있으며 키를 통해 연관된 값을 얻을 수 있다 (이 때 값에 컬렉션 프레임워크가 들어와도 괜찮음.)
  • Worst case (키워드)
    해시 충돌이 많이 발생하는 상황

해시 맵

  • 해시 충돌 해결 방식: Separate channing
  • 해시 충돌이 너무 빈번히 발생 할 경우 내부 자료구조를 변경 (LinkedList → Tree[RedBlack])
  • 내부 버킷의 자료구조를 변경하는 기준: 하나의 해시 버킷에 8개의 키-값 쌍이 모이면 내부 자료구조를 변경
  • 중복 키의 버킷 데이터가 6개로 줄어들면 다시 LinkedList로 변경

둘의 차이

Open addressing 은 데이터를 삭제 할 때 효율적이기 어려움

Open addresing 의 Liner probing, Quardratic probing, Double hashing 등 에서는 Worst case 발생 시 인덱스 위치를 특정 알고리즘을 통해 조작한다. 조작된 index 를 찾기 위해서는 해당 인덱스가 충돌이 발생하여 이동 된 것인지 아닌 것인지 확인 할 수 있어야 하는데, 이러한 구현 방식에서는 효율에 한계가 있기 때문에 삭제할 때 효율적이지 못할 수 있다.