컬렉션 프레임워크에 참여하는 두줄기 중 컬렉션(Collection)의 가장 중요한 인터페이스는

Collection, Set, SortedSet, List로 모두 대표됩니다.

나머지는 이런 인터페이스를 구현한 개별 클래스이므로 클래스이름만 알고, 클래스가

어떤 클래스를 구현것인지말 알면, 객체를 생성할 수 있고 , 객체에 적절한 인터페이스형

레퍼런스를 결합하면 폴리모피즘 덕분으로 컬렉션을 마음껏 사용할 수 있습니다.

 

컬렉션의 선택

컬레션 객체들은 태어날 때부터(설계될 때부터) 다중 thread 환경을 대비한 설계라던가,

혹은 성능 최우선 등의 설계기준에 따라 각각의 장단점이 존재하므로 컬렉션을 생성하는

부분에서 컬렉션으로서는 같은 기능을 갖고 있지만 ,어떤 객체를 생성할 것인지는 프로그램

의 성격 및 환경을 고려해야 합니다.

예를 들면, 대표적인 Set HastSet TreeSet이 있습니다.

Set s = new HashSet();   or          Set s = new TreeSet();

일반적으로 어떤 것을 많이 쓰나구요? 당근 HashSet입니다. TreeSet에 비해서 엄청

빠릅니다. 하지만 꼭 객체의 순서를 반드시 유지하거나 중요한 거라면 TreeSet

사용해야 합니다. HashSet Set이고 TreeSet SortedSet이기 때문입니다.

그러니까 TreeSet Collection이기고 하고, Set이기기도 하고, SortedSet이기고 한거지요.

당연히 TreeSet은 객체를 추가하거나 제거할 때 시간이 많이 걸릴 수 밖에 없겠지요.

저장하는 객체가 중복만 되지 않는 조건이라면 여러분은 아마 HashSet을 사용하실 겁니다.

또 한가지의 예를 더 들면, 대표적인 List Vector ArrayList , LinkedList등이 있습니다.

          List list = new Vector();

          List list = new ArrayList();

          List list = new LinkedList();

일반적으로 어떤 것을 많이 쓰냐구요? 당근 ArrayList입니다. 제일 빠릅니다.

Vector의 경우는 메소드에 synchronized 라는 키워드가 붙어 있어서 메소드 호출때마다

오버헤드가 있습니다만 ArrayList는 그런 것이 없습니다.

LinkedList의 경우는 여러분이 중간중간에 있는 객체를 삭제하는 경우가 많다면 좋습니다. 데이터형의 존재이유와 같이 데이터의 양이 상당히 많아지더라도 상수(Constant)시간으로

객체를 List에서 삭제할 수 있습니다. 하지만 ArrayList의 경우는 일반적으로 갖고 잇는 객체

의 크기에 비례합니다. , 객체가 1000개 때보다 10000개때가 훨씬 많이 느립니다.

반대로 객체를 꺼내서 참조 해야하는 경우가 많다면 ArrayList가 훨씬 좋습니다.

상수(Constant)시간으로 참조할 수 있습니다. 반면에 LinkedList는 개수에 비례하겠지요.

그것도 아주 않좋게 비례합니다.

여러분은 아마 대부분의 경우 ArrayList를 사용하지 않을까 생각합니다.

 

컬렉션의 특징

컬렉션(Collection)들은 배열과 달리 생성할 때 객체를 보관하기 위한 공간을 미리 정하지

않아도 됩니다. 배열은 선언과 동시에 100개 혹은 2000개 등의 개수를 적어주어야

하지만 컬렉션들은 그럴 필요가 없다는 것이지요. 이것이 참 매력입니다.

프로그램 하다보면 저장되어야 할 객체의 수가 동적으로 변하는데 이것을 프로그램을

만들때, 즉 컴파일시에 예상해서 프로그램하는 것이 상당히 어렵습니다.

 쓸데없이 많은 객체를 예상하게되면 메모리를 낭비하게 되고, 적게 예상하면 프로그램

새로 해야합니다. 컬렉션은 적어도 그런 걱정은 없습니다.

 처음에 컬렉션의 크기를 정하지 않아도 된다는 뜻입니다.

하지만 한가지 알려드리고 싶은 것은 모든 컬렉션은 처음에 만들어질 때 초기화된 크기,

용량을 갖고 있습니다. 객체가 계속 추가되어서 어느정도 수준이 되면 보통 자신의 현재

용량을 2배로 늘리는데, 이게 엄청나게 힘든거라 엄청 스트레스를 받습니다.

시간이 많이 걸립니다. 용량을 두배로 늘렸는데도 계속 객체가 추가가 되어 어느 정도를

또 넘으면 다시 용량을 2배로 늘립니다. 마찮가지 엄청 스트레스입니다.

이렇게 스트레스를 많이 받게 되는데 이것을 피하고자 한다면 , 프로그래머가 추가되는

객체의 정확한 수는 모르지만 어느정도 예측이 가능하다면 처음 컬렉션을 생성할 때 그

예상의 정도보다 조금 크게 초기 용량을 지정하는 것이 컴퓨터에게 스트레스를 덜 받게

하는 길입니다. 속도가 좋아진다는 뜻입니다.

200개 정도 객체가 추가 될 것 같다면 다음과 같이 하면 됩니다.

             List list = new ArrayList(250);                         

아마 성능에 도움이 될것입니다.

 

우리동네 비디오 가게

 

우리 동네 비디오 가게에서 비디오를 빌리면 대여료 및 대여기록을 남기기 위해서 전화번호

를 물어봅니다. 전화번호를 가지고 일단 회원들 자료를 검색하기 때문입니다.

비디오 가게에서 전화번호를 가지고 회원들 자료를 검색하는 것을 컬렉션을 이용하는

예제로 생각해 보겠습니다.

여기서 관심을 가져야 하는 부분은 회원정보라는 것은 객체이고,이런 회원정보 객체를

보관하고 있는 데이터소스를 생각해야 합니다. 그리고 데이터소스로부터 원하는 객체를

찾을 수 있는 알고리즘이 필요할 것입니다.

요약하면 비디오 가게 회원정보를 객체로 만들고, 회원정보를 저장하는 객체가 필요하며,

 회원정보를 저장한 객체로부터 회원정보를 검색할 수 있는 알고리듬이 필요합니다.

 

회원의 대한 정보를 PhoneBook클래스로 설계합니다.

그리고 회원정보를 저장하는 데이터소스로 컬렉션을 이용하겠습니다.

일반적으로 회원정보는 데이터소스로 하드디스크의 파일, 데이터베이스, LDAP서버등을

사용하지만, 여기서는 간단한 프로그램을 위해서 메모리를 데이터소스로 사용합니다.

 

컬렉션을 데이터베이스처럼 사용하는 것입니다.

데이터소스로 데이터베이스를 사용할 경우 회원정보를 가져올때는 SQL을 이용하겠지만,

데이터소스로 컬렉션을 이용하는 경우는 자료를 가져올수 있는 방법은 Iterator를 통하는

방법이 있고, 컬렉션을 어떤 것을 사용하는지에 따라 좀 더 다양한 방법이 있을 수

있습니다.

그럼 시작할까요?

회원정보는 전화번호,이름,주소를 포함하는 정보정도로 하겠습니다.

 

/**

* 비디오가게 회원 정보입니다.

* 전화번호,회원주소,회원이름의 정보를 갖고 있습니다.

*/

public class PhoneBook {

             private String number;

             private String address;

             private String name;

 

             public PhoneBook(String number,String address,String name) {

                           this.number = number;

                           this.address = address;

                           this.name = name;

             }

             public String getNumber() {

                           return number;

             }

             public String getAddress() {

                           return address;

             }

             public String getName() {

                           return name;

             }

             /**

             * 이름과 전화번호가 같으면 같은 회원입니다.

             */

             public boolean equals(Object o) {

                           if (o instanceof PhoneBook) {

                                        PhoneBook pb = (PhoneBook)o;

                                        if (number.equals(pb.getNumber()) &&

                                            name.equals(pb.getName()) )

                                                     return true;

                                        else

                                                     return false;

                           }

                           else

                                        return false;         

             }

             /**

             * 디버깅을 편하게 할 수 있도록 toString()메소드를 오버라이딩합니다.

             */

             public String toString() {

                           StringBuffer sb = new StringBuffer();

                           sb.append("전화번호:").append(number).append(" , ");

                           sb.append("주소:").append(address).append(" , ");

                           sb.append("이름:").append(name);

                           return sb.toString();

             }

}

예제 5 - 11 PhoneBook.java

 

PhoneBook 클래스는 회원의 이름, 회원의 주소, 회원의 전화번호를 개념화 한 것입니다.

PhoneBook은 멤버변수를 private으로 지정하고, 멤버 메소드를 public으로 지정했습니다.

그리고 public String toString() 메소드를 새롭게 정의했는데 이는 약간의 의미가 있습니다.

원래 public String toString()메소드는 java.lang.Object 클래스에서 정의되 있는 메소드

입니다. 자바의 모든 객체는 public String toString() 메소드를 갖고 있는 셈이되지요.

지금껏 필자는 은연중  객체가 갖고 있는 public String toString()메소드를 사용해 왔는데 ,

System.out.println() 메소드의 인자로 객체가 주어지면 System.out.println()은 해당

객체의 public String toString()을 호출한 결과를 출력하고 있기 때문입니다.

하지만 java.lang.Object클래스의 public String toString()메소드는 별 의미가 내용을

정의해 놓았기 때문에 여기서는 메소드 오버라이딩을 통해서 좀더 의미있는 내용,

즉 회원정보의 내용을 String으로 표현해 보았습니다. 이는 나중에 디버깅 용도로

객체의 내용을 살펴볼 경우에 아주 유용하다고 생각합니다.

일반적으로 웹사이트에서 회원이 같은 회원으로 판단하는 것은 로그인 아이디가 같은

경우는 같은 회원으로 판단합니다. 우리동네 비디오에서는 회원정보가 전화번호와

이름이 같은 경우는 같은 회원으로 판단합니다.

이런 이유로 public boolean equals(Object o) 메소드도 오버라이딩 했습니다.

 

이제는 비디오가게에서 사용하는 프로그램을 의미하는 회원관리 프로그램을 만들어

보겠습니다. 기본적으로 회원관리 프로그램은 회원정보를 "회원이름","회원의 전화번호",

혹은 "회원의 주소"로 검색할 수 있으며, 새로운 회원의 등록등을 할 수 있습니다.

물론 이러한 회원정보를 저장할 수 있는 데이터소스를 가져야 합니다.

PhoneBookManager라는 회원관리 프로그램은 데이터소스를 메모리로 사용하며,

가장 어울리는 컬렉션인 Set을 사용하겠습니다. 왜냐하면, 회원은 중복이 없는 특성이

있으므로 Set이 가장 어울리는 컬렉션이기 때문입니다.

 

import java.util.*;

/**

* 비디오가게 회원정보를 관리하는 역할을 합니다.

*/

public class PhoneBookManager {

             private Set set;      // 회원정보를 보관하는 데이타소스

 

             /**

             * 회원정보를 갖고 있는 데이타소스를 구성합니다.

             */

             public PhoneBookManager(Set set) {

                           this.set = set;

             }

             /**

             * 초기화된 회원정보 데이타소스를 구성합니다.

             */

             public PhoneBookManager() {

                           set = new HashSet();         

             }

             /**

             * 대량의 회원정보를 한꺼번에 추가

             */

             public void add(Collection c) {

                           set.addAll(c);                                 

             }

             /**

             * 회원정보를 추가합니다.

             */

             public void add(PhoneBook pb) {

                           set.add(pb);                                   

             }

             /**

             * 회원정보 데이타소스를 구합니다.

             */

             public Set getPhoneBooks() {

                           return set;                         

             }

             /**

             * 같은 이름의 회원정보만 구함

             */

             public Set getPhoneBooksByName(String name) {

            

                           Set s = new HashSet();

                           for(Iterator it = set.iterator(); it.hasNext();) {

                                        PhoneBook pb = (PhoneBook)it.next();

                                        if (pb.getName().equals(name))        

                                                     s.add(pb);

                           }

                           return s;

             }

 

             /**

             * 주소의 일부분이라도 같은 회원정보만 구함

             */         

             public Set getPhoneBooksByAddress(String address) {

 

                           Set s = new HashSet();

                           for(Iterator it = set.iterator(); it.hasNext();) {

                                        PhoneBook pb = (PhoneBook)it.next();

                                        if (pb.getAddress().indexOf(address) != -1)

                                                     s.add(pb);

                           }

                           return s;

             }

            

             /**

             * 전화번호의 일부가 같은 회원정보만 구함

             */                       

             public Set getPhoneBooksByNumber(String number) {

                          

                           Set s = new HashSet();

                           for(Iterator it = set.iterator(); it.hasNext();) {

                                        PhoneBook pb = (PhoneBook)it.next();

                                        if (pb.getNumber().indexOf(number) != -1)

                                                     s.add(pb);

                           }

                           return s;

             }

             /**

             * 회원이 몇명인가 알아봅니다.

             */

             public int getPhoneBooksSize() {

                           return set.size();

             }

}

예제 5 - 12 PhoneBookManager.java

 

PhoneBookManager 프로그램은 데이터소스로 컬렉션 Set을 가지고 있습니다.

회원정보 PhoneBook객체를 Set에 더 할 수 있으며, 조건에 맞게 회원정보를 검색할 수

있습니다.

여기서 검색에 사용하는 알고리듬은 매무 단순합니다. 회원정보를 갖고 있는 데이터소스,

Set Iterator를 통해서 검색하면서 , 검색의 인자로 들어온 정보와 같은지, 혹은 포함하는

지의 여부를 확인하는 방법을 사용합니다.

검색의 인자로 들어온 정보가 같은 것, 혹은 포함하는 회원정보만 Set으로 구성합니다.

 

그럼 PhoneBookManager를 이용해서 VideoShop를 구성해보겠습니다.

import java.util.*;

public class VideoShop {

             public static void main(String[] args) {

                           PhoneBookManager manager = new PhoneBookManager();

                           manager.add(new PhoneBook("02-555-5555","서울 길빌딩 11","홍길동"));

                           manager.add(new PhoneBook("031-525-5555","인천 성빌딩 12","성춘향"));

                           manager.add(new PhoneBook("051-525-5555","부산 부빌딩 5","홍길돈"));

                           manager.add(new PhoneBook("053-743-3333","대구 대구백화점","왕판매"));

                           manager.add(new PhoneBook("015-9244-9874","서울 성신여대","조현남"));

 

                           System.out.println("조현남을 이름으로 찾습니다.");

                           Collection c = manager.getPhoneBooksByName("조현남");

                           if (c.size() > 0) {

                                        for(Iterator it = c.iterator(); it.hasNext();) {

                                                     PhoneBook pb = (PhoneBook)it.next();                                      

                                                     System.out.println(pb);

                                        }

                           }

                           else {

                                        System.out.println("조현남은 없습니다.");

                           }

                           System.out.println("---------------------------");

                           System.out.println();

 

                           System.out.println("서울을 주소로 찾습니다.");

                           c = manager.getPhoneBooksByAddress("서울");

                           if (c.size() > 0) {

                                        for(Iterator it = c.iterator(); it.hasNext();) {

                                                     PhoneBook pb = (PhoneBook)it.next();                                      

                                                     System.out.println(pb);

                                        }

                           }

                           else {

                                        System.out.println("서울은 없습니다.");

                           }

                           System.out.println("---------------------------");

                           System.out.println();

 

 

 

                           System.out.println("5555를 전화번호로 찾습니다.");

                           c =  manager.getPhoneBooksByNumber("5555");

                           if (c.size() > 0) {

                                        for(Iterator it = c.iterator(); it.hasNext();) {

                                                     PhoneBook pb = (PhoneBook)it.next();                                      

                                                     System.out.println(pb);

                                        }

                           }

                           else {

                                        System.out.println("5555는 없습니다.");

                           }

                           System.out.println("---------------------------");

                           System.out.println();

             }

}

예제 5 - 13 VideoShop.java

 


사용자 삽입 이미지

그림 5 - 9  [ run VideoShop]

 

예제 5 - 13에서는 PhoneBookManager의 메소드로부터 얻을 수 있는 데이터형은 Set이지

, Set Collection이기도 하므로 레퍼런스를 Collection으로 구성해 보았습니다.

예제 5 - 13에서는 Collection이 가지고 있는 메소드로 만으로도 충분히 프로그램할 수

있습니다.

 

Posted by
,