2012년 10월 21일 일요일

자바의 배열리스트(ArrayList)




자바 컬렉션 프레임워크(Java Collections Framework)에서 ArrayList 클래스는 실무에서 HashMap과 더불어 가장 빈번하게 쓰이는 클래스 중 하나이므로 이번 단원에서 어떤 관점으로 ArrayList를 강의할지 필자가 상당히 고뇌(?)하였음을 미리 알리는 바이다.ㅎㅎ 동기화(synchronized)가 Vector는 지원되고 ArrayList는 지원되지 않는 차이점을 빼고는 거의 대부분 같다고 볼수 있다. 물론 ArrayList에서도 Collections.synchronizedList라는 메소드를 이용해 List를 wrapped해서 보완해쓰는 방법이나 자바 5에서 등장한 CopyOnWriteArrayList를 쓰는 방법도 있겠지만 여러분이 멀티쓰레드 환경을 고려할 필요가 없다면 그냥 ArrayList를 쓰기 바란다.(동기화 부분에 대해서는 이미 강의한바 있으니 잘 기억이 나지 않는 이들은 예전 강의를 참조하기 바란다.) 메소드의 경우에도 벡터와 태반이 비슷하며 사소한 몇가지는 여러분이 자바 라이브러리를 보면서 필요할때 쓰면 되므로 이미 저번 강의에서 Vector를 어느정도 마스터(?)한 여러분이기에 이번 강의에서는 저번과 궤를 달리하겠다. 그래도 되겠지? ㅎㅎ

오늘은 여러분의 프로그래밍 기술을 한단계 업그레이드시켜주는 관점에서 본 강좌를 진행하려고 하니 주변에 모든것을 잠시 미루고 ArrayList 강의에 총력을 다해주기 바라는 바이다.^^ ArrayList는 이미 언급한데로 Vector와 유사하므로 역시 자동으로 배열 길이를 조정할수 있으며 리스트가 찰때 알아서 길이를 조정해주므로 여러면에서 편리하다. 그렇다면 동기화를 고려할 필요가 없을경우 둘다 써도 되는 상황일때 ArrayList를 쓰는게 나은건지 Vector를 써야되는게 좋은지 고민하는 이들이 상당수 있을 것이다. 물론 상황이나 속도등 효율성에 따라 다르겠지만 정답은 없다. 그 상황에서 여러분에게 가장 적합한 방식을 쓰면되고 어떤 방식으로 구현해도 무리가 없다면 새로 나온 ArrayList를  쓰기 바란다. 옛것은 좋은 것이나 프로그래밍의 세계에서는 새로운 것을 쓰는게 여러모로 유리하다. 수고는 덜 들면서 기능은 예전보다 좋아지고 강력해지는데 점점더 편리해지는 방식을 마다할 이유가 없기 때문이다.

다시 본론으로 돌아가서, 자바 5부터 등장한 대표적인 기능 가운데 제네릭(Generic)과 enhanced for 또는 for-each라 부르는 for loop 구문을 쓸수 있는데 이미 예전 강의에서 보여준적이 있지만 ArrayList에서 이를 접목시켜 구사함으로서 얼마나 코드가 간결해지고 명확해질수 있는지 예제를 통해 저절로 습득하게 될것이다.^^ 이번 예제에서는 ArrayList를 통해 어떻게 배열을 자유자재로 다룰수 있는지 주안점을 두어 구성하였다. 또한 고혈압이나 저혈압으로 고생하는 이들에게는 천금같이 귀중한 시간(?)이 될것이라 기대하면서 예제풀이를 시작하도록 하겠다.ㅎㅎ


고혈압에 좋은음식(al): 현미
고혈압에 좋은음식(al): 완두콩
고혈압에 좋은음식(al): 옥수수
고혈압에 좋은음식(al): 닭가슴살
고혈압에 좋은음식(al): 고등어
고혈압에 좋은음식(al): 고구마
고혈압에 좋은음식(al): 당근
고혈압에 좋은음식(al): 미역
고혈압에 좋은음식(al): 버섯
고혈압에 좋은음식(al): 양파
고혈압에 좋은음식(al): 김
1=== 강이의 JAVA강좌 ===1
고혈압에 좋은음식(copy): 현미
고혈압에 좋은음식(copy): 완두콩
고혈압에 좋은음식(copy): 옥수수
고혈압에 좋은음식(copy): 닭가슴살
고혈압에 좋은음식(copy): 고등어
고혈압에 좋은음식(copy): 고구마
고혈압에 좋은음식(copy): 당근
고혈압에 좋은음식(copy): 미역
고혈압에 좋은음식(copy): 버섯
고혈압에 좋은음식(copy): 양파
고혈압에 좋은음식(copy): 김
http://alecture.blogspot.com
완두콩,옥수수
고혈압에 좋은음식(array): 현미
고혈압에 좋은음식(array): 완두콩
고혈압에 좋은음식(array): 옥수수
고혈압에 좋은음식(array): 닭가슴살
고혈압에 좋은음식(array): 고등어
고혈압에 좋은음식(array): 고구마
고혈압에 좋은음식(array): 당근
고혈압에 좋은음식(array): 미역
고혈압에 좋은음식(array): 버섯
고혈압에 좋은음식(array): 양파
고혈압에 좋은음식(array): 김
2=== 강이의 자바강좌 ===2
저혈압에 좋은음식(al2): 고추
저혈압에 좋은음식(al2): 치즈
저혈압에 좋은음식(al2): 마늘
저혈압에 좋은음식(al2): 인삼
저혈압에 좋은음식(al2): 검은콩
3=== 강이의 자바강좌 ===3
고혈압에 좋은음식(sort): [고구마, 고등어, 김, 닭가슴살, 당근, 미역, 버섯, 양파, 옥수수, 완두콩, 현미]

예제에 대한 결과값은 위와같다. 이처럼 강이의 자바강좌는 여러분의 건강까지도 챙기는 강좌이다.ㅎㅎ 조금 길어보일지 모르겠는데 배열이라 그런 것이니 긴장풀기 바라고 언제나 그렇듯 예제의 내용을 알게되면 이런거였군! 별거없네~.라는 감탄사를 연발할수 있게 될것이니 편안하게 따라오기 바란다.ㅎㅎ 예제를 통해 여러분의 건강도 되찾을수 있을것이라 기대하면서 본격적으로 예제속으로 들어가보도록 하겠다.^^

일단 패키지에서 필요한것들을 import로 불러들였다. 어떤게 있는지 대충보기 바라고 본 소스에서 보면 ArrayList를 생성하는데 <String>이라는 문구를 썼다. 이렇게 뾰족한 괄호 < >가 나오면 여러분은 아~ 제네릭 등장이군!이라고 생각하면 되는데 그냥 안써도 되게 만들지 저렇게 데이터형을 쓰도록 했는지 질문하는 이들은 잘 듣기 바란다. "안써도 된다." 허걱~ ㅎㅎ 그런데 왜 쓰는 것일까?

반대로 그럼 쓰면 무슨 장점이 있을까? 제네릭의 강력한 무기 중 하나가 바로 저렇게 객체생성할때 타입을 지정해주면 지정된 타입이외에는 받아들이지 않는다. 이것은 여러분이 리스트를 구성할때 상당히 편리해지는데 간단한 예를 들어 사원들 이름을 입력받는다고 치자. 그럼 입력받을때 문자열이 아닌 정수나 부호들은 입력해도 그 즉시 거부할수 있는 프로그램 구성이 가능해진다. 그렇지 않을경우 저번처럼 입력받고 나서 후에 캐스팅을 통해 이게 문자인지 아닌지 검열해야하는데 반해 제네릭을 쓰면 컴파일시 사전에 이를 방지할수 있으니 얼마나 유리하겠는가? 이번 예제에서도 음식들이므로 아예 스트링 타입을 지정하고 쓴것이다. 이런 제네릭(Generics)의 기능을 우리는 type-safety에 유리하다고 표현한다.

객체생성시 제네릭 쓰는 방법은 예제처럼 클래스 이름옆에 원하는 데이터형을 양옆에 적어주면 되고 나머지는 평상시 코드처럼 쓰면 된다. 그리고 ArrayList al 에다가 순서데로 현미부터 김까지 쭈욱 배열리스트에 추가하였다. 그리고 확장된 for 룹을 돌려서 출력하는 부분이다. 물론 인덱스를 이용해 인자를 증감시키면서 기존의 for 룹을 쓸수 있으나 좋은길 놔두고 외딴길로 갈 필요는 없다하겠다. 그럼 for-each 확장된 for 룹을 쓰는 방법을 설명하겠다. 괄호안에 데이터형과 변수명을 지정해주고 콜론 : (세미콜론이 아니다.)을 찍은후에 관련된 배열리스트명를 적어주고 출력란에는 초기 변수명을 다시 넣어주면 차례대로 요소를 출력한다. 이렇게 컬렉션 요소값들을 확장된 for 룹을 통해서 편하게 찍을수 있다. 자주 쓰이는 표현이니 이번 시간에 확실하게 자기것으로 만들기 바란다. 허나 외울 필요는 없다. 외우기 싫어도 저절로 외우게 될것이다. 계속해서 다음 예문에 나올것이니까 말이다.^^

다음에 분리선을 찍고 이번에는 copyList라는 배열리스트를 만든다. 여기서는 ArrayList를 똑같이 카피해서 어떻게 쓸수 있는지 보여줄려고 만든 것이다. ArrayList의 addAll( ) 이라는 메소드를 이용하면 이렇게 똑같은 배열리스트를 만드는게 가능하다.

다음은 ArrayList를 일반 배열로 넘겨받는 방법이다. 예제에서는 2가지 방법을 보여주고 있는데 ArrayList의 size( ) 메소드를 이용하는 방법과 toArray( ) 메소드를 이용하는 방법이다. 참고로 toArray( ) 메소드는 AbstractCollection 클래스에서 상속받은 메소드이다. 보는바와 같이 for 룹에서 array 리스트 대신에 a 리스트를 써줘도 결과는 같다. 그리고 다음에 보면

System.out.println(a[1]+","+array[2]);

이런 것이 나오는데 배열이 제대로 만들어졌는지 그냥 테스트해 볼려고 넣은 것이다. 결과값 두개이상 출력할때는 + 로 연결해주고 가운데 " " 쌍따옴표들은 결과값들 중간에 콤마를 넣어주려고 쓴것이다. 다 아는 것인데 설명한다고 하는 이들이 있겠지만 저게 뭐지? 한 이들도 분명히 있었을 것이다.ㅎㅎ

다음은 일반배열의 요소값들을 바로 리스트로 만드는 과정이다. 총 3가지 방식으로 만들어 보았는데 지금 예제에서 실행하고 있는 방식이랑 주석처리해 놓은 두가지 방식중 하나를 여러분이 편한데로 써먹으면 될것이다. 필자가 추천하는 방식은
List<String> al2 = Arrays.asList("고추","치즈","마늘","인삼","검은콩");
요거다. 왜냐하면 가장 편하니까~ ㅎㅎ 그리고 for 룹을 이용해 출력하는 것인데 다 아는 것이니 다음으로 넘어가보자.

벌써 마지막이다. 자바 컬렉션 프레임워크에 있는 Collections 클래스의 sort ( ) 메소드를 이용하면 예제처럼 리스트의 요소들을 차례대로 이렇게 순서데로 출력하는게 가능하다. 덧붙이자면 Collections 클래스의 메소드들은 빠른 접근을 위해 모두 static으로 구성되어 있으므로 이렇게 편하게 사용가능하다. 솔직히 sort( ) 쓸때 한글은 안될줄 알았는데 작동이 되길래 조금 놀랐다. 자바의 놀라운 위력(?)에 감탄을 금하지 않을수 없다.ㅎㅎ ArrayList에서 while문을 통해 많이 쓰이는 Iterator와 ListIterator가 있는데 이건 여러분의 정신건강(?)을 위해 다음시간으로 넘기겠다.^^

댓글 3개: