[JAVA]Collection 프레임워크(2)

Inung_92·2023년 4월 25일
2

JAVA

목록 보기
15/15
post-thumbnail

Collection 프레임워크란?

📖 데이터를 보관하기 위한 자료구조와 데이터를 처리하기 위한 알고리즘을 구조화하여 클래스로 구현해 놓은 것

지난 시간에는 Collection 프레임워크 중 List와 Set에 대해서 알아보았다. 다시 한번 특징을 간단하게 생각해보자.

⚡️ 특징

🖥️ List

  • 순서가 있으며, 객체를 일렬로 나열해놓은 구조
  • Null값이 허용되며, 이 경우 해당 인덱스는 참조를 갖지 않음
  • 동일한 객체 중복저장 가능하며 동일한 번지를 참조

🖥️ Set

  • 순서가 없이 객체를 모아둔 집합 형태의 구조
  • 객체의 중복을 허용하지 않음
  • Null은 오직 1개만 저장 가능
  • 객체를 저장한 순서와 꺼내는 순서가 다름

🖥️ Map

  • Key와 Value방식으로 구성된 Entry 객체를 저장하는 구조
  • Key값 중복 불허, Value 중복 허용(Key가 중복된 Value의 동일한 번지를 참조)
  • 동일한 Key값이 저장될 시 기존 Key값을 대체

위와 같이 Collection 프레임워크의 간단한 특징들을 알아보았다. 이번 게시글에서는 지난 시간에 배운 List와 Set을 제외한 Map이라는 인터페이스에 대하여 알아가 보도록 하자.


Map

⚡️ 특징

  • Key와 Value방식으로 구성된 Entry 객체를 저장하는 구조
  • Key값 중복 불허, Value 중복 허용(Key가 중복된 Value의 동일한 번지를 참조)
  • 동일한 Key값이 저장될 시 기존 Key값을 대체

Map의 특징 중 Entry 객체는 Key에 해당하는 객체와 Value의 해당하는 객체를 짝을지어 저장할 수 있는 객체이다. 즉, Map에는 객체 타입이 2개가 저장이 가능하다. Key와 Value의 객체 타입이 동일할 수도 있고, 다를 수도 있기 때문에 Map을 사용할 때에는 어떤 Key값에 대한 Value를 저장할지 고민하는 것이 중요하다.

⚡️ 구조

⚡️ 하위 클래스

🖥️ HashMap

동기화를 미지원하며, 해시 함수를 통해 Key와 Value가 저장되는 위치를 결정하며, 대량의 데이터를 검색하는데 성능이 뛰어남

해시 함수를 통해 저장되는 위치가 결정되기 때문에 사용자는 객체의 저장위치를 알 수 없으며 Null값이 허용된다. 또한 당연하게도 Map을 구현하기 때문에 Key값은 중복되지 않는다.

HashMap은 List와는 다르게 저장공간을 2배씩 늘리기 때문에 가능하다면 초기용량을 지정해주는 것이 메모리 관리 및 성능 향상에 도움이 된다.

개념도

put()을 통해 Key와 Value로 구성된 Entry 객체를 저장하면 각 객체는 해시함수를 통해 위치가 지정되어 저장된다. 이때 저장된 위치는 사용자가 알 수 없다. 이 후 get()을 통해 Key값을 이용하여 Value를 호출하면 해시함수를 통해 해당 Key값이 참조하는 Value 객체를 반환하는 것이다.

기본문법

//선언
HashMap<String, String> map1 = new HashMap<String, String>(); //기본적인 생성
HashMap<String, String> map2 = new HashMap<>(); //타입 파라미터 생략 생성
HashMap<String, String> map3 = new HashMap<>(map1); //다른 HashMap의 정보를 가진 HashMap 생성
HashMap<String, String> map4 = new HashMap<>(10); //초기용량(capacity) 지정 가능
HashMap<String, String> map5 = new HashMap<>(10, 0.7f); //초기 capacity, load factor 지정
HashMap<String, String> map1 = new HashMap<String, String>(){{
	put("a", "b");
}};; //선언과 동시에 초기화

//추가 및 삭제
map.put("A", "에이");
map.put("B", "비");

map.remove("A");

map.clear(); //전부삭제

🖥️ HashTable

기본적으로 HashMap과 비슷한 구조를 가지지만 동기화 지원

HashTable은 HashMap과 기본적으로 비슷한 구조를 가진다. 다만, 차이라면 Null이 허용되지 않는다는 점과 동기화를 지원한다는 점이다. 여기서 한번 생각해야하는 것은 HashMap은 Thread-safe하지 않는다는 점으로 반드시 동기화 처리를 해주어야하고, HashTable은 동기화가 지원되기에 Thread-safe하며 동기화를 별도로 처리할 필요가 없다는 점이다.

기본문법

//선언시 자료형과 생성자에 타입 명시
HashTable ht1<Integer, Integer> ht1 = new HashTable ht1<Integer, Integer>();

//타입명시 x, 초기타입으로 Object로 설정됨
HashTable ht2 = new HashTable();

//인스턴스 생성 시 타입생략 가능
HashTable<Integer, Integer> h3 = new HashTable();

//초기captcity 지정
HashTable<Integer, Integer> h4 = new HashTable<Integer, Integer>(10);

//선언과 동시에 초기값 지정
HashTable<Integer, Integer> h5 = new HashTable<Integer, Integer>(){{
	put(1, 100);  //Integer는 기본자료형의 포장객체이기 때문에 당연히 다른 객체자료형도 가능
	pub(2, 200);
}};

다른 문법들은 HashMap과 마찬가지로 Map을 구현하기에 거의 유사한 형태를 보인다고 생각하면된다.

⚡️ 반복을 통한 객체 반환

배열 또는 List의 경우 순서가 있는 자료구조로 반복문을 통해 index에 해당하는 객체를 순차적으로 반환할 수 있다. 하지만 Set이나 Map은 순서가 없기 때문에 해당 객체를 호출하기 위해서는 객체 자체 또는 Key값을 파라미터로 넘겨야 반환 받을 수 있는데 이러한 불편함을 해결해주는 것이 Iterator 객체이다.

🖥️ Iterator란?

반복자라고도 불리며 객체 지향적 프로그래밍에서 배열이나 그와 유사한 자료 구조의 내부의 요소를 순회(traversing)하는 객체

🖥️ 사용이유

Collection 프레임워크 내에서 동일한 인터페이스를 제공하여 공통적으로 사용하기에 간편하다는 점이 가장크다. 즉, List/Set/Map 객체에서 모두 사용가능하기에 코드의 재사용이 용이하고 유지보수가 편리하다는 점이 있다.

다만, 반복문보다는 속도가 느린데 이유는 반복문의 경우 증가하는 index를 반복적으로 접근하여 호출한다면 Iterator는 index에 해당하는 객체를 내부적으로 생성하고 순차적으로 조회한다. 이렇게하면 index의 초기값부터 접근하는 반복적인 문제는 사라지지만 객체를 생성하는 과정에서 지연시간이 발생하는 것이다.

🖥️ 사용방법

//Map 선언
HashMap<String, String> hashMap = new HashMap();
hashMap.put("a", "에이");
hashMap.put("b", "비");
hashMap.put("c", "씨");

//Iterator 생성
//Map의 Key 집합인 keySet()를 통해 Set 자료형으로 변환 후 iterator()를 통해 생성
Iterator<String, String> it = hashMap.keySet().iterator();

//반복문 실행
while(it.hasNext()){ // 다음 요소가 있는지 확인(있으면 true, 없으면 false)
	String data = it.next(); // 다음 요소 반환
    System.out.println(data);
}

Iterator를 이용한다면 모든 Collection 프레임워크의 하위 클래스들은 동일한 인터페이스로 같은 동작을 할 수 있게 되는 것이다.


마무리

이렇게해서 Collection 프레임워크의 기본적인 내용들을 살펴보았다. 사실 인터페이스 및 클래스들의 메소드를 하나하나 뜯어보면 차이점들이 존재하지만 그 부분에 대해서는 아직 정확히 다룰 수 있는 정도의 지식수준이 아니기 때문에 기본적인 부분에 대해서만 다뤄보았다.

Collection 프레임워크를 잘 활용하면 복잡한 로직에 대해서도 비교적 간단하게 구현되는 경우들이 있다. 특히, 코딩테스트를 해결하는 부분에서 많이 활용되니 코딩테스트를 준비한다면 Collection 프레임워크를 사용하는 연습을 같이하면 더욱 좋을 것이라는 생각이 든다.

다음 시간에는 Collection 프레임워크를 구현하는 하위 클래스들의 메소드를 하나씩 살펴볼 수 있는 게시글을 작성하려한다.

그럼 이만.👊🏽

profile
서핑하는 개발자🏄🏽

0개의 댓글