Java에서 여러 데이터를 하나의 집단으로 사용하기 위해 지금까지 필자가 사용한 방식은 다형성을 이용한 클래스의 상속 또는 Object 객체의 배열을 만드는 것이었다. 하지만 배열 형태의 자료를 다루기에는 여간 귀찮은 것이 한 두 가지가 아니다. 기본적으로 배열은 크기 조절이 불가하다는 점으로 인해 데이터의 추가와 삭제 시 새 배열을 만든 뒤 arraycopy 등의 매서드로 배열을 복사하는 작업이 수없이 진행되어야 한다. 또한 이러한 작업이 반복되면 메모리 공간 또한 낭비가 될 수 밖에 없다.
이러한 이유로 Java는 컬렉션 프레임워크(Collection Framework)라는 것을 제공한다. 말 그대로 Collection, 즉 '데이터 집단'을 쉽게 다룰 수 있는 Framework(작업 틀)을 제공한다는 것인데, 컬렉션 프레임워크는 배열 시 자주 사용하는 기능을 여러 인터페이스와 클래스로 구현해 놓아 배열의 세세한 작업에 시간을 빼앗기지 않고 본업에 집중해 줄 수 있도록 한다. 마치 공장에서 반복적으로 일어나는 - 과자의 틀을 찍어내는 것과 같은 일들을 틀을 찍는 기계를 만들어 돌리는 것과 유사하다.
컬렉션 프레임워크는 연관된 인터페이스와 매서드가 다양하다. 따라서 하나의 포스팅으로 마무리를 절대 할 수 없기에, 이번 포스팅에서는 Java 컬렉션 프레임워크의 개요와 컬렉션 프레임워크 등장 전 사용했던 유사 클래스에 대해 알아보려 한다.
1. 컬렉션 프레임워크 개요
컬렉션 프레임워크는 Collection 인터페이스를 최상위 계층으로 하는, 데이터 군 취급하는 인터페이스와 클래스를 하나로 일컫는 용어다.
Java 공식 Documentation 문서를 보면 이 Collection은 요소(element)라고 불리는 객체들의 그룹을 상징한다고 하며, 하위 인터페이스로 Set과 List를 제공한다고 나와있다. Collection을 구현하는 클래스는 매우 다양하기 때문에 클래스를 제외하고 지금까지 파악한 구조를 나타내면 아래와 같다.
그럼, 저 Set과 List는 왜 나뉘어져 있는 것일까? 조금 전에 보았던 문서 스크린샷의 붉은 박스 안을 자세히 보면, Collection의 일부는 요소값의 중복을 허용하고, 일부는 순서를 허용한다는 대략적인 내용이 보인다. 여기서 Set은 요소값의 중복을 허용하지 않는 반면, List는 요소값의 중복을 허용한다. 그리고 List는 요소의 순서, 즉 시퀀스(Sequence)를 가지지만 Set은 요소의 순서를 고려하지 않는다. Set을 구현하는 클래스로는 LinkedSet, HashSet 등 Set으로 끝나는 대부분의 클래스이며, List를 구현하는 클래스는 ArrayList와 LinkedArrayList 등이 있다.
이들 인터페이스를 구현하는 클래스는 클래스명에 Set과 List가 접미사로 붙지만, Stack과 Vector처럼 List에 포함됨에도 불구하고 List라는 접미사를 사용하지 않는 클래스도 있다. Java의 컬렉션 프레임워크는 JDK의 초반에 나타난 것이 아니라 Java의 버전이 업데이트 되는 와중에 생긴것이기 때문에 컬렉션 프레임워크가 탄생하기 이전에 유사한 기능은 Stack과 Vector가 대신하고 있었다. 이것이 마치 사람의 맹장처럼 흔적기관(?)같이 남아 Documentation에 표시되는 것이고 말이다.
하지만 데이터를 단순히 배열과 유사하게 값만 나열하는 Set과 List로는 모든 정보를 효율적으로 표현할 수 없다. 왜냐하면 각 Index에 위치한 값이 무엇을 의미하는지 처음 코드를 보는 사람들은 알 수 없기 때문이다(혹여 만든 사람이라 하더라도 나중에 기억을 되돌려 떠올리기는 쉽지 않다). 따라서 Python의 Dictionary와 동일한 기능을 하는 Map이라는 인터페이스가 별도로 제공된다.
Map은 Key와 Value, 즉 키와 값으로 구성되어 있는 데이터 군이다. 만약 누군가의 인적 정보를 Map 형태로 표시한다면 아래와 같이 나타낼 수 있다.
{"이름": "Alex", "성": "Java", "나이": 22, "거주지": "경기도 고양시 일산동구 장항1동", "연세": 22...}
따라서 하나의 키는 하나의 값만 가지며 키는 중복이 될 수 없다. 하지만 위와 같이 값(Value)은 여러 키에 중복이 가능하다. 마치 순서를 고려하지 않는 Set과 비슷해보이나 Set과는 달리 값이 중복될 수 있다는 점에서는 List와도 유사해보인다.
Map 인터페이스에 해당하는 클래스는 Set과 List와 마찬가지로 대부분의 클래스 명 어미에 Map이 붙어있다.
지금까지의 내용을 종합하여 표현하면 위의 그림과 같다. 물론 이 그림상에 포함되지 않은 인터페이스와 클래스도 많지만 자주 사용할만한 것 위주로 나타내보았다. 컬렉션 프레임워크는 모두 java.util 패키지에 속해있다.
2. Vector
Vector는 컬렉션 프레임워크가 등장하기 전 사용되었던, 배열을 효율적으로 다루기 위한 클래스다. 따라서 배열 작업 시 필요한 배열의 크기 조절이라던가, 값의 추가 삭제 등의 매서드가 모두 정의되어 있다. 초창기의 Java에서는 Object 클래스를 직속으로 상속했으나, 컬렉션 프레임워크의 등장으로 List 인터페이스를 구현하는 클래스가 되었다.
Vector는 인스턴스화를 통해 객체를 생성한다. 생성자는 기본형을 포함하여 4가지다.
생성자 매개인자는 대부분 Vector의 배열 크기와 관련이 있다. 기본형은 10개의 배열을 제공하며, initialCapacity의 수에 따라 제공되는 배열의 크기가 달라진다. 참고로 Vector에서 다루는 배열은 protected 제어자가 적용되어 Vector를 상속하는 클래스가 아닌 이상 이 배열을 건드릴 수 없다.
잘 보면 Vector는 입력값의 수와 배열 크기를 별도로 관리하게 되어 있다. 이를 나타내는 매서드들이 각각 size()와 capacity()다. 이제 add() 매서드로 값을 추가하여 입력값 수가 어떻게 변하는지 알아보자.
이제 값을 제거해보자. 필자는 추가한 3개의 값들 중 가운데 값인 "Hello"를 제거할 것이다. 가운데 값을 제거하면 index 1의 값은 null로 변할까? 아니면 바로 뒤의 값인 "Java"가 이 자리로 이동할까? 위에서 필자가 주석을 달아놓은 부분을 잘 보신분들이라면 대략 눈치채셨겠지만, "Java" 값이 index 2에서 1로 이동한다.
만약 Object 객체 배열로 가운데 값을 삭제하고 삭제된 부위 뒤쪽의 값들을 옮기는 작업을 진행한다고 하면 System.arraycopy 등을 사용하여 배열의 일부를 잘라 복사하는 과정을 몇 번 씩 거쳐야 하기 때문에 코드가 복잡해진다. 하지만 Vector의 remove() 매서드는 매서드 내에 이를 모두 정의해놓아 매서드 호출만으로도 쉽게 배열 가운데의 값을 삭제하고 위치를 조정하는 것이 가능하다.
또한 Vector는 StringBuffer와 StringBuilder 클래스에서 보았던 것처럼 trimToSize()라는 매서드를 제공하여 쓸데없이 낭비되는 메모리가 발생하지 않도록 도와준다.
Vector는 배열과 유사하기 때문에 매서드의 사용도 크게 어렵지 않다. 특정 index의 값을 얻는 것은 get() 매서드를, 특정 값의 index 위치는 indexOf() 매서드를, 특정 위치의 값을 바꾸는 것은 set() 매서드를 사용하면 된다.
Vector는 실제 배열에 입력된 값과 배열의 크기를 별도로 관리해야한다는 불편함과 더불어, 배열 작업에 필요한 몇몇 기능들이 누락되어있다. 이 때문에 컬렉션 프레임워크가 탄생하면서 Vector 클래스에 기능을 추가하고 단점을 보완한 ArrayList클래스가 탄생하게 되었다.
Vector 말고 Stack 역시 컬렉션 프레임워크 탄생 전에 존재하던 클래스이긴 한데, 이 녀석은 추후 Queue라는 클래스와 함께 살펴볼 예정이다.
다음 포스팅에서는 List 인터페이스에 속한 ArrayList와, ArrayList의 단점을 보완한(그러나 장점도 깎아먹은) LinkedList에 대해 알아보려 한다.
Fin.
'Java > Java Basic' 카테고리의 다른 글
[Java Basic] 33 - 컬렉션 프레임워크3 (Stack, Queue) (0) | 2022.09.01 |
---|---|
[Java Basic] 32 - 컬렉션 프레임워크2 (ArrayList, LinkedList) (0) | 2022.09.01 |
[Java Basic] 30. 형식화 클래스 (0) | 2022.08.26 |
[Java Basic] 29. 날짜 및 시간 관련 클래스 (0) | 2022.08.24 |
[Java Basic] 28. Wrapper 클래스와 기타 클래스 (0) | 2022.08.22 |
댓글