프로그래밍을 하다보면, 여러 데이터를 담아놓기 위해 자료구조를 많이 사용하게 된다. 자료구조를 편의성있게, 공통적으로 추상화된 기능을 제공하기 위해 Collection 인터페이스를 자주 사용하게 된다.
ArrrayList는 다음과 같이 List, RandomAccess, Clonable, Serializable을 구현하고 있다.
인터페이스 |
용도 |
Serialziabe | 객체를 저장하거나 파일에 저장할 수 있음을 의미 |
Clonable | Object로 부터 상속 받은 clone() 메소드를 사용할 수 있음을 의미 |
Iterable | 객체를 순회할 수 있으며, foreach의 문장을 사용할 수 있음을 의미 |
RandomAccess | 임의로 데이터에 접근하는 알고리즘이 적용된다는 것을 의미 |
2. LinkedList
LinkedList는 ArrayList와 달리 노드 단위로 저장이된다. LinkedList는 맨 앞을 가르키는 노드와 맨 뒤를 가르키는 노드를 갖고 있으며, 노드는 다음과 같이 데이터를 저장하는 item과 다음 요소를 참조하는 next, 이전 요소를 참조하는 prev 변수를 갖고 있는 것을 볼 수 있다따라서, 데이터를 저장할 때, 실제 데이터 뿐 만아니라 앞뒤의 참조를 위한 추가적인 저장공간이 필요함을 알 수 있다.
3. Vector
Vector는 ArrayList와 비슷한 자료구조이며, ArrayList와 같이 내부적으로 배열을 사용해 데이터를 저장하며, 별도의 지정없이 10의 크기를 같은 배열을 갖고 있다. 제공하는 기능도 ArrayList와 매우 유사하다.
4. Stack
Stack은 Vector를 상속받은 자료구조이며, LIFO의 구조를 가진다.
우선, ArrayList와 Vector의 가장 큰 차이점은 연산 시, synchronized의 적용여부다.
ArrayList | Vector |
---|---|
Vector를 연산할 때는 synchronized를 통해서 멀티스레드 환경에서 안전하다. 하지만, synchronized의 키워드로 인한 하나의 쓰레드만 접근할 수 있으므로 성능상은 좋지 않다. 이와 달리, ArrayList는 synchronized를 통한 동기화를 제공하지 않아, 멀티 스레드에서 안전하지는 않지만, 빠른 접근이 가능하다.
(참고 : Vector 내부에 구현된 메소드는 synchronized를 통해 동기화를 제공하지만, 이는 메소드 단위의 synchronzied를 제공한다. 따라서, 멀티 스레드에서 삽입과 삭제를 동시에 접근하는 상황이 나온다면, 멀티스레드 환경에서 Thread-safe 하지않다는 것을 유의하자)
다음은 Stack이다. Stack자료구조는 용도가 명확하다. Last-In First-Out의 구조를 갖는 자료구조이므로 LIFO구조가 필요한 곳에서 쓰면 된다. (추가로, Stack은 Vector를 상속받았고, 또 Vector와 같이 모든 메소드를 synchronized로 동기화를 제공한다.)
참고 1) https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html
참고 2) https://inpa.tistory.com/entry/JCF-%F0%9F%A7%B1-ArrayList-vs-Vector-%EB%8F%99%EA%B8%B0%ED%99%94-%EC%B0%A8%EC%9D%B4-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0