Java Advent Calendar 2017 11日目の記事です。
のがみんちょといいます。JavaとAWSの狭間で生きてます。
みなさんEclipse Collectionsはご存知でしょうか。
2004年にGoldman Sachsが開発し、その後OSSとなって2015年にEclipse Foundationに移管されました。
Eclipse Collectionsとは?の内容は、他の資料でまとまっているものがあるため、
イケてるところ、イケてないところにフォーカスしてお伝えします。
Eclipse Collectionsとは?
上記の通り、一般的な内容は、焼き直しになってしまうため割愛します。
下部記載の参考資料を参照してください。
イケてるところ
ファクトリメソッドのAPIが統一的
Java9でもコレクションのファクトリメソッドがリリースされましたが、これはイミュータブルなものです。
Eclipse Collectionsでは、List, Set, Mapなどのコレクションを統一的なAPIで初期化できます。
MutableList<String> list = Lists.mutable.of();
MutableSet<String> set = Sets.mutable.of();
MutableMap<String, String> map = Maps.mutable.of();
// ofの代わりにwithも利用可
MutableList<String> list = Lists.mutable.with();
// immutableの場合も呼び出し方法はほとんど同じ
ImmutableList<String> list = Lists.immutable.of();
多数のデータ構造がある(特にMultimapとPartition)
EclipseCollenctionsでは以下のようなデータ構造をサポートしています。
データ構造 | 対応するプリミティブ |
---|---|
List | |
Set | |
SortedSet | 順序つきSet |
Bag | 重複ありSet |
SortedBag | 順序つきBag |
Map | |
BiMap | 双方向マップ |
SortedMap | 順序つきMap |
Multimap | キーに対応するバリューがコレクション。List, Set, Bagから選択可 |
Stack | |
Pair | Tuple形式のデータ |
PrimitiveCollection
StreamAPIにも、IntStream, LongStreamなどPrimitiveなStreamはありますが、データ構造としてはList-likeな取扱いしかできません。
前項のコレクション全てに対してPrimitiveなコレクションが存在します。
ラッパークラスを利用するよりも、メモリ効率がよく大量データを処理する場合、顕著に差が出ます。
引数にメソッド参照が利用できるメソッドが存在する
Java8で悩みどころだったのが、Predicateを引数に取るメソッドでは、メソッド参照が利用できませんでした。
Eclipse Collectionsでは、複数メソッドにwithの接尾辞があるものがあり、メソッド参照を有効活用できます。
// Java8での記述
boolean result = this.people.stream().anyMatch(person -> person.hasPet(PetType.CAT));
// Eclipse Collectionsに書き換え
boolean result = this.people.anySatisfy(person -> person.hasPet(PetType.CAT));
// withを用いた場合
boolean result = this.people.anySatisfyWith(Person::hasPet, PetType.CAT);
(参考資料2より引用)
Mapのイテレートが容易
StreamAPIで悩みだったのが、「MapのすべてのValueを変換する」処理が簡潔に書けないものでした。
Eclipse CollectionsのMutableMapには、keyValuesViewというメソッドが存在し、一括での処理が用意になりました。
Maps.mutable.of("Key1", 1, "Key2", 2, "Key3", 3, "Key4", 4)
.keyValuesView() // RichIterable<Pair<String, Integer>>
.collect((k, v) -> Tuples.pair(k, v * 2))// RichIterable<Pair<String, Integer>>
.toMap();
イケてないところ
RichIterable#min、RichIterable#maxが、NoSuchElementExceptionをthrowする
これらはOptionalが開発される前から存在したメソッドです。
空のコレクションでこれらのメソッドを呼び出すと、NoSuchElementExceptionをthrowします。
利用時には空チェックが必須になります。
と書いていたんですが、Eclipse Collections 8.2でRichIterable#minOptional、RichIterable#maxOptionalが追加されていました。
弱点ない・・・?
さいごに
主観で自分がいいなとおもっているものを書きつらねました。
QiitaにもまだEclipse Collectionsの記事は少ないので、利用している方は一緒に布教活動しましょう!