IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  자바 | 오픈 소스  >

불필요한 코딩을 줄이자!

아파치 Commons Lang 클래스 네 개로 코드 재사용의 이점을 배워보자

developerWorks
Go to the previous page11 페이지 중 5 페이지Go to the next page

문서 옵션

샘플 코드


제안 및 의견
피드백

튜토리얼 평가

이 컨텐츠를 개선하기 위한 도움을 주십시오.


무던하게 Comparable 인터페이스 구현하기

다소 수학적 형식에 따르는 규약을 요구하는 또 하나의 흥미로운 메서드로 Comparable 인터페이스의 compareTo 메서드가 있다. 이 인터페이스는 특정 객체들의 순서를 결정하는 데 세부적인 제어가 필요할 때 꽤 중요하다. 이 절에서는 Commons Lang의 CompareToBuilder를 사용하는 법을 살펴 보겠다.

출력 순서 지정하기

이전 자바 프로그래밍 경험 덕에 이미 눈치챘을 수도 있지만 특정 경우에 대해서는 객체 순서를 어떻게 결정할지에 대한 기본 방식들이 있다. Collections 클래스의 sort 메서드가 그런 예다.

예를 들어 Listing 15의 Collection은 순서가 없고 그냥 그대로 두면 그대로 남아 있을 것이다.


Listing 15. String 리스트

ArrayList<String> list = new ArrayList<String>();
list.add("Megan");
list.add("Zeek");
list.add("Andy");
list.add("Michelle");

Listing 16처럼 listCollections 클래스의 sort 메서드에 넘겨주면 기본 순서가 적용될 것이다. 이 경우 기본 순서는 알파벳 순이다. Listing 16은 Listing 15에 보인 이름 리스트를 정렬해 알파벳 순서로 정리된 결과를 출력한다.


Listing 16. String 리스트 정렬

Collections.sort(list);

for(String value : list){
 System.out.println("sorted is " + value);
}

Listing 17에 출력 결과를 보였다.


Listing 17. String들을 정렬한 출력 결과

sorted is Andy
sorted is Megan
sorted is Michelle
sorted is Zeek

이게 제대로 동작하는 이유는 당연하지만 자바의 String 클래스가 Comparable 인터페이스를 구현하고 따라서 알파벳 순서로 정렬하도록 compareTo 메서드가 구현되어 있기 때문이다. 사실 자바 언어의 거의 모든 핵심 클래스가 이 인터페이스를 구현한다.

Account 객체들이 다양한 방법으로 정렬되어야 한다면 어떻게 해야 할까? 예를 들어 id나 성(last name) 기준으로 말이다. 어떻게 할 수 있을까?

당연하지만 먼저 Comparable 인터페이스를 구현하고 compareTo 메서드를 구현해야 한다. 이 메서드는 본질적으로 자연스러운 순서(natural ordering)를 위해서만 사용될 수 있다. 즉, 객체가 자신의 프로퍼티에 따라 정렬될 때에 한한다. 결과적으로 compareTo 메서드는 equals 메서드와 꽤 비슷하지만 Account 컬렉션이 프로퍼티에 따라 정렬되는 걸 허용한다. 프로퍼티는 compareTo 메서드를 통해 처리된다.

이 메서드 구현에 관한 문서를 읽는다면 이 메서드가 equals와 아주 비슷함을 발견할 것이다. 즉, 제대로 작성하기가 까다롭다(Effective Java는 이 주제에 대해 4페이지를 할애한다). 이제 의심할 여지 없이 이 패턴을 이해했을 것이다. Commons Lang을 활용할 것이다.




위로


compareTo 구현하기

Commons Lang은 CompareToBuilder라는 적절한 이름이 붙은 클래스를 제공한다. 이 클래스는 EqualsBuilder와 거의 똑같이 동작한다. 사슬 형태로 연쇄 호출할 수 있는 append 메서드가 있고 최종적으로 toComparision 메서드를 통해 int 값을 돌려준다.

따라서 compareTo를 구현하려면 먼저 Listing 18처럼 Account 클래스가 Comparable 인터페이스를 구현하도록 해야 한다.


Listing 18. Comparable 인터페이스 구현하기

public class Account implements Comparable {}

다음으로 Listing 19에 보인 것처럼 compareTo 메서드를 구현해야 한다.


Listing 19. compareTo의 기본 구현

public int compareTo(Object obj) {
 return 0;
}

이 메서드 구현은 두 단계 과정이다. 먼저 넘겨 받은 인자 타입을 원하는 타입으로 변환한다(이 경우는 Account). 그리고 CompareToBuilder를 이용해 객체의 프로퍼티들을 비교한다. Commons Lang 문서에 따르면 equals 메서드에서 비교한 것과 같은 프로퍼티들을 비교해야 한다. 따라서 Account 객체의 compareTo 메서드는 Listing 20과 같아야 한다.


Listing 20. CompareToBuilder 사용하기

public int compareTo(Object obj) {
 Account account = (Account) obj;
 return new CompareToBuilder().append(this.id, account.id)
  .append(this.firstName, account.firstName)
   .append(this.lastName, account.lastName)
    .append(this.emailAddress, account.emailAddress)
     .append(this.creationDate, account.creationDate)
      .toComparison();
}

정말 코딩을 줄이고자 한다면 Listing 21처럼 리플렉션 형태의 CompareToBuilder API를 사용할 수도 있음을 잊지 말자.


Listing 21. CompareToBuilder의 리플렉션 API 사용하기

public int compareTo(Object obj) {
 return CompareToBuilder.reflectionCompare(this, obj);
}

이제 예를 들어 Account 객체의 집합이 자연스러운 순서에 따라 정렬되어 있다는 점을 이용하려고 한다면 Listing 22에 보인 것처럼 Collections.sort를 사용할 수 있다.


Listing 22. Account 객체 정렬하기

Date now = new Date();
ArrayList<Account> list = new ArrayList<Account>();
list.add(new Account(41, "Amy", "Glover", "ajg@me.com", now));
list.add(new Account(10, "Andrew", "Glover", "ajg@me.com", now));
list.add(new Account(1, "Andrew", "Blover", "ajg@me.com", new Date()));
list.add(new Account(2, "Andrew", "Smith", "b@bb.com", now));
list.add(new Account(0, "Andrew", "Glover", "z@zell.com", new Date()));

Collections.sort(list);

for(Account acct : list){
 System.out.println(acct);
}

이 코드는 객체를 먼저 id, 다음으로 이름, 그 다음으로 성 등의 자연스러운 순서에 따라 객체들을 출력한다. 결과적으로 정렬 결과는 Listing 23과 같을 것이다.


Listing 23. 정렬된 Account 객체들

new Account(0, "Andrew", "Glover", "z@zell.com", new Date())
new Account(1, "Andrew", "Blover", "ajg@me.com", new Date())
new Account(2, "Andrew", "Smith", "b@bb.com", now)
new Account(10, "Andrew", "Glover", "ajg@me.com", now)
new Account(41, "Amy", "Glover", "ajg@me.com", now)

이 결과가 말이 되냐는 다른 문제다. 다음 절에는 Commons Lang이 더 읽을 만한 결과를 만들도록 도와줄 수 있음을 알게 될 것이다.




위로



Go to the previous page11 페이지 중 5 페이지Go to the next page
    IBM 소개 개인정보 보호정책 문의