소프트웨어를 개발하다보면 Collection에 담겨있는 객체에서 일부 데이터만 추출해 새로운 Collection으로 변환해야 하는 경우가 있다. 예를 들어 User 객체가 있는데 이 User 객체에서 사용자 이름만 가지는 Collection이 필요한 경우이다.
동적 파이핑 언어에서는 쉽게 처리할 수 있는데 자바에서는 좀 귀찮은 것이 사실이다. 구글에서 제공하는 guava library (http://code.google.com/p/guava-libraries/)를를) 활용해 일정 부분 개선할 수 있지만 이 또한 부족한 것이 사실이다. 그래도 좀 더 깔끔한 방법일 수 있으니 다음과 같이 구현해보자.
Function<SocialUser, String> userToString = new Function<SocialUser, String>() {
public String apply(SocialUser user) {
return user.getUserId();
}
};
Collection<String> userIds = Collections2.transform(searchedUsers, userToString);
자바는 Functional 언어가 아니다보니 위와 같이 처리할 수 밖에 없을 듯하다. 내가 모르는 더 좋은 방법이 있으려나. 아는 분 있으면 공유 좀. 위처럼 새로운 라이브러리 익히는 것보다 기존처럼 그냥 Collection 하나 만들어서 순환하는 것이 더 좋은 분도 있을 듯하다.
9개의 의견 from SLiPP
제가 그동안 쓴 코드는 위처럼 apache commons을 써왔는데요, guava를 쓰는 것도 깔끔한 것 같습니다. apache commons를 썼더니 type casting하는 게 지저분하네요.
@freeism 뭐 코드를 보니까 원리는 똑같네요. 단지 다른 점이라면 generic을 써서 캐스팅을 하느냐 하지 않느냐의 차이네요.
마찬가지 방법으로, Goldman Sachs Collections 에서는 다음과 같이 하고 있네요.
방식 자체는 거의 동일할 것으로 보입니다. 일단 이 모습만 놓고보면, 저라면 이런 작업에는 Goldman Sachs Collections를 사용할 듯 합니다.
@Kenny Goldman Sachs Collections는 Function을 만드는 과정은 똑같은데 최종적으로 Function을 사용하는 방식이 다르네. 근데 Goldman Sachs Collections와 같은 접근 방식을 취할 경우 Collection Data가 Goldman Sachs Collections의 Collection(위 예에서는 MutableList)로 변환해야 하는 이슈가 있지 않을까? 기존 JDK Collection에 담겨 있는 데이터라면 Guava와 같은 접근 방식이 더 낫지 않을까라는 생각이 든다. 네가 제시한 Goldman Sachs Collections을 활용할 경우 어떤 측면에서 더 좋을까? 나는 Collection 변환 작업이 있어서 더 불편할 거 같은데.. 내가 모르는 뭔가 있는 듯 한데 이야기 좀 해주라.
@자바지기
음... 설계차원의 이야기로 넘어가게 되겠네요. (물론, 제가 제시하는 방법이 옳다! 라는건 아닙니다. 코드는 보는 사람마다 다르게 짤 수 있으니까요.) 제가 이해한 부분으로 설명드리면 이렇게 되겠네요.
TO_LAST_NAME 혹은 userToString 혹은 transform은 어디에 속해야 하는가?
collect 에 관한 이야기
결론적으로, 두 가지 다 제가 보는 관점에서는 method의 위치 문제 입니다. Goldman Sachs Collections 쪽이 좀 더 납득이 가는 위치에 method가 있는걸로 보여요.
@Kenny Function<SocialUser, String> userToString의 위치에 대해서는 딱히 고려해 보지 않았는데 네 이야기 들어보니 그와 같은 접근 방식이 맞겠다는 생각이 든다. 일단 이 부분에 대해서는 공감한다. slipp.net 소스 코드 리팩토링 함 해야겠다.
두번째로 collect 관련해 나 또한 언어적으로 이 기능을 지원한다면 Goldman Sachs Collections와 같이 구현하는 것이 좋겠다는 생각이 든다. 그런데 자바의 경우 JDK Collection API를 쓰고 있는데 Goldman Sachs Collections API를 쓰기 위해 새로운 Collection에 담아야 하는 것이 좀 찜찜하다는 의견이다. 물론 처음부터 Goldman Sachs Collections에 담으면 좋겠지만 프레임워크들을 사용하다보면 그렇지 않은 경우들이 많이 발생하니까.
@자바지기 원론적인 의미에서 어느정도 동의 합니다. 하지만, 대부분의 경우에 Java Collection API를 그대로 쓰는 경우는 없어요. 프레임워크를 예로 들어도, 기본적으로 ResultSet으로 돌아온 일종의 HashMap을 변환하는 과정이 들어가게 되니까요. 용도에 맞게 데이터 타입을 변경하는건 일상적인 프로그래밍에서 흔한 일이라, 저라면(^^) 저런 문제가 있는 경우에는 Goldman Sachs Collections를 사용할 것 같다는 의미였습니다~
아래와 같은 코드를 SocialUser의 static 메소드로 구현하고 SocialUser.TO_USERID 형태로 구현을 하는 것은 어떨까요?
Function<SocialUser, String> TO_USERID = new Function<SocialUser, String>() { public String apply(SocialUser user) { return user.getUserId(); } };
저희 팀 에서는 Collection 객체를 다룰때 lambdaj library 를 보편적으로 사용하고 있습니다.
의견을 남기기 위해서는 SLiPP 계정이 필요합니다.
안심하세요! 회원가입/로그인 후에도 작성하시던 내용은 안전하게 보존됩니다.
SLiPP 계정으로 로그인하세요.
또는, SNS 계정으로 로그인하세요.