Java 의 Vector 와 ArrayList , Linked List 의 차이점

IT 바라보기/Programming


              [공지]연극 [스캔들] 초대이벤트! 진행中! (~5/29 까지)
              [공지]연극 [시간을 파는 상점] 초대이벤트! 진행中! (~6/4 까지)

Java의 리스트 클래스를 이해하자!


Java에서 대량의 자료를 추가/삭제하며 처리하기 위해서는 무엇을 사용해야 할까요?

연구실에서 Java를 한번쯤 공부해 본 사람이라면 보통 “Vector Class”라고 대답을 할 것입니다. 정답이죠. Vector Class는 대량의 자료를 가질수 있으며, 추가/삭제또한 자유롭게 처리가 가능합니다. 그럼 뭐가 문제라서 이런 글을 쓰는것일까요?

단순히 “처리되는가” 를 넘어서 “빠르게 처리할수 있는가” 를 생각해 본다면,
위에서의 대답 “Vector Class” 는 X에 가까운 답이라고 할 수 있기 때문입니다.

우선, Java에서 제공하는 “대용량 자료처리 개념” 은 여러가지 상위 인터페이스를 통해서 구현할 수 있습니다. (Collection, Iterator, Enumeration, Map등등) 각각 독특한 특징을 가지고 있습니다만, 이번에 다룰 내용은 Collection이하의 객체들이 되겠습니다.(나머지에 대해서도 다음 기회에 이야기 하도록 하겠습니다.)

Collection Interface는 “내부에 포함되는 요소는 순서를 가진다” 라는 특징을 가지고 있습니다. (이와 반대로 포함요소가 순서에 관계없이 저장되는녀석이 Map계열입니다.)
Collection을 계승(상속)해서 실제 구현된 객체들도 여럿 있습니다만, 그중에서도 대표적인 ArrayList, LinkedList, Vector 의 특징을 간단하게 설명하면 다음과 같습니다.
(HashSet, TreeSet같은 특이한 녀석들도 있습니다만… 일반적인 경우에 사용되는 녀석들은 아닌관계로, 설명은 다음기회로 넘기겠습니다…)

사용자 삽입 이미지


1.      Vector

Java 1.0때 만들어져, 지금까지 유지되어온 클래스.
1.0버젼에서는 지금과 같은 List관련 객체들은 없었습니다.
이 버젼대에서 애용되었던 것이 Vector입니다.

Vector의 기본적인 동작은 다음에 설명할 ArrayList와 동일하기 때문에 넘어가기로 하고, 다른점만 설명하겠습니다.
Vector와 이후에 등장하는 List객체의 다른점은 “동기화(synchronize)”처리에 있습니다.
우선 “동기화” 라고 하는 개념에 대해서 간단하게 짚고 넘어가도록 하겠습니다.

두명의 학생이 하나의 컴퓨터를 사용하려고 합니다. 사용순서에 제한이 없기 때문에 서로 먼저 사용하려고 싸우게 되죠. 그러다보니 다음과 같은 상황이 발생합니다. 학생A가 워드로 “가나다라마바사…. ”를 적고 있는도중에 학생B가 키보드를 가로채서 “ABCDEFG…”를 입력해 버립니다. 두 학생은 하나의 자원(컴퓨터)를 공유하지만, 사용 순서에 대한 제한이 전혀 없기때문에 서로 상대방의 자료를 덮어써 버리는 일이 발생하게 되죠.
이것을 방지하기 위해서 자바에서는 synchronized 라는 키워드를 만들어 두었습니다. 이 키워드를 사용하면 공통된 자원에 접근하는것은 [반드시 한번에 하나!] 라는 조건이 붙게 되죠. 한 스레드(학생A)이 공유자원(컴퓨터)에 작업을 마치기 전 까지는 다른 스레드(학생B)가 공유자원(컴퓨터)에 접근을 할 수 없도록 약속해 버리는 것입니다. 이런 과정을 “동기화” 라고 합니다.

복수의 스레드로부터 데이터의 추가/삭제처리가 이루어졌을경우에도 내부의 데이터는 “안전”하게 한번에 한 스레드씩 처리가 이루어지도록 되어있다는 것이죠. 데이터의 안정성을 놓고 보았을때, 정말 좋은 일이 아닐수 없습니다.
… 만, 동기화가 문제시 되는 경우는 어디까지나 “공유자원”과 “복수사용자” 가 존재할때 성립되는 것입니다. 한개의 자원을 하나의 스레드가 사용하는 경우에도 동기화를 고려해서 처리를 하게 되면, 오히려 성능의 저하를 가져오게 되는 문제가 발생하죠. Vector의 경우는 “무조건 동기화” 이기 때문에 단일 스레드 처리에서는 앞으로 설명할 ArrayList나 LinkedList보다 성능이 떨어집니다. 자바 1.2 부터의 Vector의 주 사용목적은 1.0버젼과의 호환성이라고 생각하시는게 가장 좋을겁니다. 거의 쓸 일이 없다는 거죠. 혹시 동기화처리가 필요한 경우는 Vector를 이용하기 보다는 Collection. synchronizedCollection(Collection c)나synchronizedList, Map을 이용하는것이 성능상 바람직하겠습니다.

2.      ArrayList

Java2 (1.2)에서 새로이 도입된 Collection의 구현객체입니다.

자료의 추가/삭제 등 기본적인 기능은 Vector와 동일하나, 내부적인 자동 동기화 기능이 삭제되어있죠. 때문에 다수의 스레드 환경에서 사용하기 위해서는 Vector설명에서 이야기했었던 Collection. synchronizedCollection(Collection c)를 이용해서 동기화 옵션을 설정해 주면 됩니다.
이름에서 알 수 있듯이, 내부적으로 자료를 Array(배열)구조로 가지고 있는 객체이죠. 데이터의 추가 / 삭제를 위해서 내부적 임시배열을 작성후 데이터를 복사하는 방법을 사용하고 있습니다.

사용자 삽입 이미지

때문에, 대량의 자료를 추가 / 삭제하는 경우에 내부적인 처리량이 늘어나서 상당한 성능저하를 가져옵니다. (C에서 배열에 데이터 추가/삭제 해 보신분은 아시리라 믿습니다.)
대신, 각 데이터의 인덱스를 가지고 있기 때문에, 필요한 데이터에의 접근이 한번만에 가능하죠. (C에서 포인터를 이용해서 한방에 원하는 데이터에 접근하는것과 같습니다.)
보통, 많은 데이터를 한번에 몽땅 가져와서 여러번 참조해 쓸 때 최상의 성능을 나타내는 객체가 되겠습니다.
간단한 예로 정리를 하면,
물건을 사기위해서 5명의 사람이(손님 A,B,C,D,E) 의자에 앉아 차례를 기다리고 있는데,미리 순서를 예약해 둔 F라는 사람이 C의 앞에 불쑥 들어서서 자리를 비켜달라고 합니다. 예약을 했기때문에 C는 비켜야 하죠. 결국, C는 D의 자리로. D는 다시 E손님의 자리로 한칸씩 밀려나게 됩니다. 그럼 E는? 의자 옆에 빈 공간에 쭈그려 앉던지, 아니면 새로 의자를 요구해야 하겠죠.
이런 손님이 몇백명 있을경우에 도중에 한사람이 끼어들게 되면 뒤로 밀려야 할 사람의 수가 장난이 아니겠죠? 그런 처리를 내부적으로 해 주는것이 ArrayList객체가 되겠습니다.


3.      LinkedList

연구실에서 C를 배우고 계시거나, 이미 C단계를 지나신 분들이 이해하기 쉬운 말로 바꾸면 “연결리스트” 입니다. 앞과 뒤의 구조체 주소를 가진 녀석들이 죽 ~ 나열된 모습. 그것이 바로 LinkedList객체의 실체입니다.

사용자 삽입 이미지

LinkedList의 내부구현


이녀석은 순서대로 늘어선 것이 아니라, 다음에 나올 자료의 위치정보만 가지고 있습니다. (앞과 뒤 모두 가진 객체도 있습니다.) 자기가 몇번째인지의 정보는 관심도 없죠.
Vector, ArrayList같이 인덱스정보를 가진 녀석들과의 차이점은 무엇일까요?
바로 추가 / 삭제의 용이함에 있습니다.

사용자 삽입 이미지

LinkedList에서의 데이터 추가


위의 그림에서 알 수 있듯이, 어떤 정보를 도중에 추가하기 위해서 다른 정보들을 뒤로 밀어내는 처리가 필요없습니다. 간단하게 글로 표현해 보면,
A-B-C-D 4명이 눈을 가린채, 서로 손을 잡고 있다고 하죠. 손을 잡기 전에 서로 다음에 오는 사람이 누군지만 확인을 한 상황입니다. 이 상태에서 E라는 사람을 B다음에 세우려면 어떻게 해야 할까요?
간단합니다. B의 손을C가 아닌 E를 잡도록 하고, E의 손이 C를 잡도록 살짝~ 도와만 주면 끝입니다. 요것이 LinkedList내부의 추가 처리입니다.(삭제는 역순임으로 설명은 생략)
데이터의 추가가 빈번하게 일어나는 자료를 처리하기 위한 객체라고 할 수 있습니다. 하지만, 데이터의 검색면에서는 어떨까요?

사용자 삽입 이미지

LinkedList에서의 데이터 검색

조금전의 예 – 손을 마주잡고있는 사람들 A-B-E-C-D 중에서 C를 찾아내서 물어볼것이 있습니다. 이 경우 어떻게 해야 하나요? ArrayList의 경우는 “몇번째 녀석이 C이다. “ 라는 목록을 내부적으로 가지고 있기 때문에 한번에 접근이 가능합니다. ... 만, LinkedList는 그런 목록을 가지고 있지 않기때문에, 최초의 정보A로부터 하나씩 검토를 해 나가야만 합니다.
A에게가서 C의 위치를 물어봐도 A는 B가 어디있는지 밖에 모르기때문에 B에게 가서 다시 C의 위치를 물어봐야 합니다. B는 E의 위치밖에 모르니 E에게 가서 또 물어봐야 하죠. 결국 E가 C의 위치를 알려주게 됩니다만… 확률적으로 n개의 데이터가 들어있을경우에 운이 좋으면 1번에, 운이 나쁜경우는 n번 움직여야만 원하는 데이터를 찾을 수 있게 됩니다. 데이터의 검색에는 그다지 적합하지 않은 녀석이죠.
(자료구조 같은 과목에서 검색패턴에 대한 좋은 이야기를 많이 들을 수 있을거에용~ ^^)

이야기를 정리하면,

  • Vector – 구버젼 호환용. 그다지 사용되지 않음. 동기화 처리가 내부적으로 일어남으로 다른 객체보다 무거움.

  • ArrayList – 배열의 복사에 의한 데이터 저장처리를 내부적으로 행하며, 각 데이터에 대한 인덱스를 가지고 있기때문에 검색이 매우 빠르다. 다만, 많은 데이터의 추가 / 삭제시에는 배열의 복사가 빈번하게 일어나, 성능이 떨어지는 단점이 있다.

  • LinkedList – 다음 자료의 위치정보를 가지며, 내부적인 인덱스는 가지고 있지않다. 데이터의 추가 / 삭제는 위치정보의 수정만으로 가능하기 때문에 많은 정보의 추가 / 삭제처리가 필요할때 유용하다. 다만, 데이터가 많은 경우의 검색시 처음 자료로부터 순차적으로 찾아 나가야 하기 때문에 느려지는 단점이 있다.

아직 설명하지 못한 많은 저장 객체들이 존재합니다만…
일반적으로 사용되는 3가지에 대해서 간단하게 적어보았습니다.
왜 비슷한 기능을 가진 녀석들이 여러개 존재하는걸까~ 라고 생각하신다면 각각의 객체가 가지는 특징과 성능차에 대해서 공부해 보는것도 좋을거라고 생각합니다.

실제로 프로그램이라는건 “동작” 하는건 당연한거죠. 보다 좋은 “성능”을 낼 수 있느냐가 중요하다고 생각합니다.
0.01초의 성능차이도 동작하는 환경에 따라서는 생명선이 될 수도 있으니까요.

모두들 좀 더 재밌게~ 그리고 깊게 공부하시는데 조금이나마 보탬이 되었으면~

하는 마음에서 간단하게 적어보았습니다. ~  m(_ _)m



신고
Name
Password
Homepage
Secret
이전 댓글 더보기
funnyshake 2010.09.09 13:11 신고 URL EDIT REPLY
정보 감사합니다 블로그로 담아갑니다.
http://blog.naver.com/funnyshake
나그네 2010.09.24 16:28 신고 URL EDIT REPLY
본문을 못가져가네요 ^^
주소만 떼어갑니다.~ 잘봤습니다.
감사 2010.10.26 16:48 신고 URL EDIT REPLY
저도 주소만 담아갑니다.
묭사 2010.10.28 20:42 신고 URL EDIT REPLY
잘보고가요~ 복받으실꺼에요~
R 2011.10.16 22:22 신고 URL EDIT REPLY
와 설명이 정말 쉬워서 잘 이해되었습니다 감사함당~
하늘다래 | 2011.10.17 10:19 신고 URL EDIT
이 많은 댓글들에 답변을 못달고
젤 최근에 달아주신 분께^^;

좋은 자료가 됐다니 다행이네요^^
팔랑도깨비 2011.10.21 15:07 신고 URL EDIT REPLY
http://blog.daum.net/palranggoblin/203

퍼갔습니다!! 정말 잘 읽었습니다^^
doogi 2012.01.31 11:05 신고 URL EDIT REPLY
잘봤습니다. 정리가 잘 되어 있어서 궁금한점 해결하고 갑니다!
드러머 2012.12.07 17:25 신고 URL EDIT REPLY
오~Java 관련 검색하다가
우리팀 보컬의 블로그가 나와서 깜짝놀랐습니다.
오~이렇게 활동을 하고 계시다니..
놀랍습니다.
좋은 정보들을 이렇게 올리시니 멋지시네요~^_^ b
참고로 전 드러머~ㅋㅋㅋ
화이팅하세요!
하늘다래 | 2012.12.07 21:04 신고 URL EDIT
헉.............
두 분 중 누구신가요 ㄷㄷㄷㄷㄷ
부...부끄럽습니다 ㄷㄷㄷㄷ
팡팡v 2013.09.13 11:37 신고 URL EDIT REPLY
ArrayList에 index가 있어서, C에서 포인터를 이용해서 한방에 원하는 데이터에 접근하는것과 같다고 하셨는데, 이건 틀린말 입니다.

index는 순서를 세면서 갑니다.

예를 들어
ArrayList<Integer> list = new ArrayList<>();
// list 안에 값이 있다고 치고

for(int a : list){
System.out.println(a);
// 첫번째 반복문 에서 index : 0
// 두번째 반복문 에서 index : 0 -> 1
// 세번째 반복문 에서 index : 0 -> 1 -> 2
// 네번째 반복문 에서 index : 0 -> 1 -> 2 -> 3
// ....
// 뒤쪽으로 갈 수록 느려지게 됩니다.
}

때문에 커서를 사용하는 이터레이터가 나온 겁니다.
Iterator<Integer> it = list.Iterator();
while(it.hasNext){
int a = it.next();
System.out.println(a);
// 첫번째 반복문 에서 cursor: 0
// 두번째 반복문 에서 cursor: 1
// 세번째 반복문 에서 cursor: 2
// 네번째 반복문 에서 cursor: 3
}

커서는 반복문을 수행하고 그자리에 멈춰 있기 때문에 성능이 좋습니다.

marvell | 2014.02.07 21:16 신고 URL EDIT
제가 틀린거면 죄송하지만 카운팅을 처음부터 다시 한다는건 처음들어본거 같습니다. index가 그냥 0, 1, 2 이렇게 증가하지 처음부터 카운팅을 세지는 않습니다. arraylist를 보면 원래 list에서는 한번에 접근을 못하지만 array특성이 있기 때문에 한번에 접근이 가능한 것이지요. 예를들면 generic 데이터에 따라서 메모리에 일정 간격이 설정되어있을겁니다. 0000 0010 0020 이런식으로...arraylist에서 2번째로 get해버리면 포인터가 0020을 지정해서 list와는 다르게 한번에 접근이 가능한 것이지요. Iterator는 객체들의 의존관계를 없애기 위해 나왔으며, 객체를 생성하고 key값을 복사하는 등의 단계를 거치기 때문에 for문이 더 빠를 수도 있습니다.
nahj53 2014.08.19 11:28 신고 URL EDIT REPLY
정말 이해하기 쉽네요 ㅎ
제 개인 블로그에 위 내용 사용해도 될까요??
윗 댓글 보니까 출처 남기면 가능한 것 같은데
출처는 당연히 남기구요 ㅎ 일단은 개인자료로 사용하고 있을게요 ㅎ
문제 시 되면 말씀 해 주세요
제 블로그는
http://blog.naver.com/nahj53 입니다.
하늘다래 | 2014.08.19 14:23 신고 URL EDIT
그대로 복사-붙여넣기 하시면 안되고,
링크로 소개하시는 것은 괜찮습니다. ^^
무중력고기 2014.11.04 16:50 신고 URL EDIT REPLY
비유가 아주 이해하기 쉽네요.
동찜 2015.04.30 02:41 신고 URL EDIT REPLY
감사합니다 개인블로그에 퍼갈게요
DOOD 2015.10.03 15:22 신고 URL EDIT REPLY
자바를 접한지 얼마 안되서인지, Vector 는 처음 알고 가네요.
ArrayList LinkedList 차이 확실히 배우고 갑니다.
정말 좋은글이네요.
감사합니다!
Seph 2016.03.31 15:10 신고 URL EDIT REPLY
설명이 정말 잘 되있네요.^^ 참고하여 블로그에 제 나름대로 보관해두려고 합니다. 감사합니다 ^^
jake kim 2016.08.31 09:42 신고 URL EDIT REPLY
Vactor ... 구버전과 호환성을 위해서 존재한다는 건 잘못된거 같은데요.
아래 ArrayList 개념도문제가 있습니다. 코어 쪽 공부하시는 분들은 이글 보시면 안되요 Vactor의 경우 Traversing 속도에서 ArrayList와 확연한 속도 차이가있습니다. 훨씬 빨라요. 이글은 카더라에 가깝습니다.
COCOMO 2017.01.25 17:12 신고 URL EDIT REPLY
몇 줄 안읽었는데도, 이해가 정말 잘돼요... 감동입니다.. 선댓글 후감상하겠습니다. 감사합니다 ^^
SJ 2017.02.03 09:28 신고 URL EDIT REPLY
감사합니다. 덕분에 이해가 잘 되었습니다.
D.Story 2017.03.27 19:14 신고 URL EDIT REPLY
설명을 잘해주셔서 블로그에 정리하는데 내용 참고 좀 하겠습니다. 감사합니다.
뽀록이야 2017.08.08 08:58 신고 URL EDIT REPLY
좋은글 감사합니다.
나랑놀자 2017.09.05 16:25 신고 URL EDIT REPLY
설명을 아주 이해하기 쉽기 잘 하시네요. 감사합니다~