목적
다양한 Collection Framework 를 살펴보며 비교하고
이러한 프레임워크를 통하여 이용할 수 있는 유용한 도구는 어떤 것들이 있는지 살펴보고 어떻게 사용하는지 확인합니다.
그리고 실제 업무에서 사용된 사례를 확인하여 어떻게 응용할 수 있는지 알아보기 위하여 작성되었습니다.
목차
- Collection 이란?
- Collection Framework 란?
- 우리가 사용하는 Collections
- Collection Framework 별 특징
- 성능비교(가능한 것들만 추려서)
Collection 이란?
정의
- 다수의 데이터를 쉽고 효과적으로 처리할 수 있는 표준화된 방법을 제공하는 클래스의 집합을 의미
- 즉, 데이터를 저장하는 자료 구조와 데이터를 처리하는 알고리즘을 구조화하여 클래스로 구현해 놓은 것
Java에서는 Collection을 Interface로서 제공하고 있으며 이 Interface로 구현한 것을 “컬렉션 프레임워크"라고 합니다.
대표적인 Interface로서 List, Set, Map 이 있습니다.
Collection Framework 란?
정의
넓게는 Collection의 각 Object 그룹을 저장하고나 조작하기 위한 통합된 아키텍처를 의미합니다.
List, Set 등의 Interface를 구현한 구현 클래스를 제공합니다.
Collection Framework 계층 구조
우리가 사용하는 Collection Framework
1. JDK-Collections (Default) (since JDK 1.2)
2. apache-commons-collections
3. spring(core)-util: CollectionUtils
4. google-guava-collection
5. eclipse-collections
Collection Framework 별 특징
1. Apache Commons Collection
소개
Java Collection 프레임워크를 좀 더 강력하게 사용할 수 있는 구현체가 제공되고, Collection 처리를 쉽게 할 수 있는 몇몇의 추가적인 기능을 새로운 인터페이스와 구현체 및 유틸리티로서 제공합니다.
다양하고 새로운 인터페이스와 구현체의 소개 그리고 주요 기능(& 특징위주) 보기
- Bag: 컬렉션을 단순화하고 객체가 컬렉션에 나타나는 횟수를 계산하는 컬렉션을 정의합니다.
예를 들어 Bag에 {a, a, b, c, d, d} 가 정의되어 있을 때 getCount(”d”)를 하면 d 가 들어있는 수 “2”를 반환하고 uniqueSet을 이용하면 고유한 값을 반환합니다. - BidiMap: 양방향 맵을 지원하기 위한 인터페이스. 양방향 맵을 사용하여 키를 조회하거나 값을 이용하여 키를 조회할 수 있습니다.
- MapIterator: JDK의 Map 인터페이스는 EntrySet 혹은 KeySet 을 통해 반복수행하여 제어하기가 다소 어렵습니다. MapIterator는 보다 쉽게 반복이 가능한 Map 조작 인터페이스를 제공합니다.
- Transforming Objects
- Ordered Map Interface
- Merge & Sort (합치고 정렬)
- Filtering Objects
- Comparator implementations
- Iterator implementations
Apache commons collections 에 대하여 더 알아보기
Apache Common Collections − Reference for Apache Commons Collections. Commons Collections User Guide − User guide Reference for Apache Commons Collections.
2. Spring(core)-util: CollectionUtils
소개
Collection 사용을 위한 잡다한 기능을 모아놓은 Utility 메서드들의 모음입니다. Spring framework 의 util 패키지에 기본으로 포함되어 제공됩니다.
Apache commons에 비하면 아주 빈약한 구성을 확인할 수 있지만 별도의 라이브러리 추가 없이 Spring framework 를 사용한다면 바로 이용할 수 있는 장점이 있습니다.
주요 Method 훑어보기
- arrayToList(Object source)
- contains, containsAny
- mergeArrayIntoCollection
- hasUniqueObject
3. google-guava’s Collection
소개
Guava는 구글이 작성한 자바 오픈소스 라이브러리입니다. (*처음 만들어졌을 때는 google-collections 였으나, Guava 로 이름이 변경되었습니다.)
다른 컬렉션 유틸리티들과 마찬가지로 유용한 함수들과 클래스들을 다양하게 제공하고 있습니다.
이곳에서는 컬렉션에 대해서 설명하지만 Guava 프로젝트에는 Graphs, Caches, Strings, Math 등의 많은 유용한 기능들을 제공하고 있습니다.
<< JDK 1.5 부터 사용할 수 있음! >>
언제 사용할까?
앞서 소개한 컬렉션들과 마찬가지로 대부분 아래와 같은 분야에서 사용할 수 있습니다.
- 반복문
- Temporary collections
- Mutable / Immutable collections
- if ( x == null): NPE 방지 (Optional 사용 JDK1.7부터 사용가능)
- ETC ...
주요 기능
- Functions and Predicates
- Filter
- 예쁘게 컬렉션 만들기
4. Eclipse Collections
소개
골드만삭스에서 10년동안 내부적으로 사용하기 위해 개발된 후 GS 컬레견으로 오픈소스로 제공되었고 2015년에 Eclipse 재단에 마이그레이션되고 이후 Eclipse Collection 이라는 이름으로 현재 계속 업데이트되고 있습니다.
컨셉
홈페이지에 소개된 내용에 의하면 “풍부하고 간결하며 읽기 쉬운 API 라는 컨셉으로 등장하였으며 Java 8의 Lambda 표현식 및 메서드 참조의 성능을 극대화합니다.”
예를 들면 아래와 같은 데이터를 추출할 때 다음과 같이 사용할 수 있게 됩니다.
Java 8 Lambda | Esclipse Collections |
|
|
단순히 코드의 양을 봤을 때 줄여든 모습이 보이지만 그 보다 더 좋은 부분은 읽기가 확실히 편해졌다는 것입니다.
Java8의 람다식도 충분히 훌륭하지만(이전의 버전에 비하면) Eclipse Collection의 경우에는 사람이 읽기에도 편해졌습니다. (filter하여 조건의 값을 추출하여 Collection 한다는 뜻을 select 라는 간결함으로 풀어냈습니다.)
우리가 사용한 곳
우리 프로젝트에서는 “선택할인묶음 상품” 구현 중 아래의 유효성 검사가 필요한 일이 있었습니다.
내용은 ‘같은 상품이 수량, 통화' 정보가 같으면 입력할 수 없도록 하는 것이 목표였습니다.
논리로 표현하자면 → “중복을 제거한 데이터를 추출하기 (단, 1, 2, 3이 같은 경우)"
즉, DB에서 조회한 데이터 중 “여러 조건"에 해당하는 데이터를 중복제거하여 가져와야 하는 상황이 있었습니다.
그것을 Eclipse Collection의 ListIterate라는 Utility class 를 이용하여 깔끔하게 정리한 기록이 있습니다.
if (product.getProductCompositionType().equals(ProductCompositionType.SELECT_DISCOUNT)) {
List<ProductPrice> productPrices = product.getProductPrices();
List<ProductPrice> distinct = ListIterate.distinct(productPrices,
HashingStrategies.fromFunctions(ProductPrice::getProduct
,ProductPrice::getQuantity ,ProductPrice::getCurrencyType));
if(BooleanUtils.isFalse(distinct.size() == productPrices.size())) {
throw new NotAcceptableException(ExceptionCode.E01200100);
}
}
그러면 다른 컬렉션에도 기능이 있는지 궁금하실텐데, 사실 Eclipse Collection을 찾게 된 계기가 ... 찾지 못해서 입니다. (있다면 알려주세요!!)
특징
당연한 이야기겠지만 Java의 기본컬렉션은 물론이고 그를 활용한 보다 많은 다양한 방식의 Collection을 구성하고 데이터를 조작할 수 있습니다.
이전에 찾아본 Apache Commons의 Bag과 같은 유용한 클래스들과 Mutable, Immutable Collections 그리고 기본 클렉션등을 활용할 수 있습니다.
// 기본형
// 예제;1 ~ 10까지 연속되는 수의 컬렉션 만들기
IntInterval oneTo10 = IntInterval.fromTo(1, 10);
// 가변형(Mutable)
MutableList<String> mutableListOf =
Lists.mutable.of("One", "One", "Two", "Three");
MutableList<String> mutableListWith =
Lists.mutable.with("One", "One", "Two", "Three");
// 불변형(Immutable)
ImmutableList<String> immutableListOf =
Lists.immutable.of("One", "One", "Two", "Three");
ImmutableList<String> immutableListWith =
Lists.immutable.with("One", "One", "Two", "Three");
with 와 of = 찾아봤는데 코드의 주석에는 아래와 같이 나와있었어요.
Same as {@link #with ... }
그리고 성능에 관한 이야기 입니다.
테스트를 했을 때 객체의 수가 적을 땐 오히려 성능이 느렸거나 비슷했었다고 하면 객체의 수가 많아지면 많아질 수록 성능은 더 좋은것으로 파악되었습니다.
위의 그래프는 공식 홈페이지에서 가져온 것이며 아래와 같이 설명하고 있습니다.
효율적인 컨테이너(를 사용하여) 메모리 사용량 감소
어떤 원리일까요?
조사한 자료에 의하면 아래와 같은 여러 이유들로 성능이 좋다고 합니다.
- JDK HashSet과는 다른 UnifiedSet을 사용하여 메모리 성능을 향상
- 최적화된 Eager API 사용
- Hashing 전략을 기반으로 하는 여러 구현체를 제공
- Lazy 처리와 병렬 Lazy API
- MultiReader Collection
- 기존 JDK(최소 9까지는)에서는 병렬처리를 할 때 컬렉션의 동기화는 조건적으로 스레드로부터 안전하다고 합니다. 실제로는 안전하지 않고 수동으로 개발자가 처리해야할 부분이 많다는 의미가 됩니다.
- 그러나 이러한 방법은 까다롭고 완벽하고 할 수 없습니다.
- Eclipse Collections의 MultiReader Collection을 사용하면 컬렉션 내부에서의 읽기 잠금, 쓰기 잠금을 모두 사용할 수 있게하여 안전하게 객체의 데이터를 조작할 수 있습니다.
- 결국 병렬처리를 할 수 있게됨으로써 성능에 이점을 얻을 수 있을 것 같습니다.
Eclipse Collections 와 JDK Collection 성능비교
JDK-Collection vs Eclipse-Collections: https://www.baeldung.com/jdk-collections-vs-eclipse-collections
저는 위 사이트의 git 저장소 데이터를 가져와 테스트를 해봤습니다.
테스트는 숫자의 덧셈과 해당 숫자를 ImmutableList, MutableList에 넣어 비교하는 것과
Member 라는 임의의 클래스를 생성하여 데이터를 생성한 다음 filter 를 통해 추출한 데이터를 각각 비교하는 테스트입니다.
- 여러번 테스트를 수행하면서 조금씩 차이가 생기긴 했지만, 특히 MemberListFilterUnitTest의 경우에는 실행할 때마다 속도가 엎치락 뒤치락 했습니다.
- Eclipse Collection의 소개에서는 성능이 뛰어나다 라는 장점이 있지만, 개발자가 올바르게 사용하지 않는다면 오히려 성능을 기대하기는 어려울 수 있음을 의미하는 것 같습니다. (테스트 3을 의미함)
정리
우리가 사용하는 다양한 컬렉션에 대해 알아봤습니다. 중요한 것은 이 컬렉션은 JDK Collection을 도움주는 도구라고 볼 수 있습니다.
그렇기 때문에 무조건 이 컬렉션이 답이다 저것이 답이다 라고 하긴 어려운 부분이 있고 기능으로서 필요하다면 상황에 맞게 가져와 사용한다면 좋지 않나 생각합니다.
그럼에도 불구하고 사용하는 컬렉션이 너무 많거나 중복되는 기능이 많다면 한번은 검토해봐야하지 않을까? 생각합니다.
감사합니다.
자료출처
- What is Collection: https://www.javatpoint.com/collections-in-java
- Eclipse Collections: https://www.eclipse.org/collections/
- Eclipse Collections Reference Guile: https://github.com/eclipse/eclipse-collections/blob/master/docs/0-RefGuide.adoc
- Eclipse Collections Evolutions: https://www.infoq.com/articles/eclipse-collections/
- Collection Vs Collections In Java: https://www.w3schools.blog/collection-collections-java
- Collection ? Collections ? : https://livenow14.tistory.com/43
- Collection Framework: https://livenow14.tistory.com/31, https://choicode.tistory.com/25
- Ten reasons to use Eclipse Collection: https://medium.com/oracledevs/ten-reasons-to-use-eclipse-collections-91593104af9d
- 5 Reasons why should use guava: https://blog.outsider.ne.kr/710
- Java filter usage samples: https://zetcode.com/java/filterlist/
- Quick example of Guava: https://www.slideshare.net/tfnico/google-guava
- Google Guava for cleaner code: https://www.slideshare.net/mitemitreski1/google-guava-for-cleaner-code?next_slideshow=13556442
'Languages > Java' 카테고리의 다른 글
Java-HTTPS 통신 (링크) (0) | 2013.10.18 |
---|---|
Java-HTTPS 주소의 파일 다운로드 (0) | 2013.10.16 |
JAVA-현재 시간의 날짜 간단하게 표현하기 (0) | 2013.03.07 |
Bad version number in .class file` faultDetail:`null` (0) | 2012.08.15 |
JAVA excute / excuteUpdate / excuteQuery 차이점 (0) | 2012.08.15 |