#概要
Eclipse Collections自体の解説については、他に良い記事がたくさんあると思うので、ここでは「〇〇がしたい」と思った時にすぐ参照できるリファレンスとしてアップします。
とりあえず、よく使うものをリストアップしてみましたが、他に出てきたら追加するかもしれません。
※ほとんどList系しか書いてません。
#環境
Ver.8.0.0
すみません、普段仕事で使っているバージョンという事で、若干古めです。
<dependency>
<groupId>org.eclipse.collections</groupId>
<artifactId>eclipse-collections-api</artifactId>
<version>8.0.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.collections</groupId>
<artifactId>eclipse-collections</artifactId>
<version>8.0.0</version>
</dependency>
#初期化
##空のリスト
Lists.mutable.empty();
これ以降、特に断りを入れませんが、mutable(MutableList)のほかにimmutable(ImmutableList)も使えます。
ImmutableListは、add等のメソッドが存在せず、変更不可になっています。
※ソート系など、一部MutableListでしか使えないメソッドがありますので、ご注意ください
Lists.immutable.empty();
##まとめて初期化
Lists.mutable.of(first, second, third);
##Iterableを元に初期化
java.util.List等をImmutableList等に変換できます。
Lists.immutable.ofAll(hogeList);
#頻出パターン集
##条件を満たす要素だけを取り出す
ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo");
assertThat(
hogeList
.select(s -> s.contains("g"))
.makeString()
, is("hoge, fuga")
);
##条件を満たす要素があるかどうか確認したい
anySatisfy
は、条件を満たす要素が1つでもあれば、trueを返します。
ListIterable<String> hogeList = Lists.mutable.of("hoge", null, "fuga");
assertThat(
hogeList.anySatisfy(s -> s == null)
, is(true)
);
##全ての要素が条件を満たさない事を確認したい
noneSatisfy
は、条件を満たす要素が1つもなければ、trueを返します。
ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo");
assertThat(
hogeList.noneSatisfy(s -> s.equals("hogera"))
, is(true)
);
##1つでも条件を満たす要素があれば取得したい
detect
は、条件を満たす要素のうち、最初の1つだけを取り出します。
ListIterable<String> hogeList = Lists.mutable.of(null, "hoge", "fuga");
assertThat(
hogeList.detect(s -> s != null).toString()
, is("hoge")
);
##要素を変換し、新しいListにする
ListIterable<String> hogeList = Lists.mutable.of("hogehoge", "fuga", "piyopi");
assertThat(
hogeList
.collect(s -> s.length())
.makeString()
, is("8, 4, 6")
);
##重複排除
重複を排除し、ユニークな要素のみ残す。
ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo", "fuga", "piyo");
assertThat(
hogeList
.distinct()
.makeString()
, is("hoge, fuga, piyo")
);
ユニークと判断する基準を指定する事も可能。この時、結果のリストに残るのは、重複している要素のうち最初の1つのみ。
ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo", "fugafuga", "piyopiyo");
assertThat(
hogeList
.distinct(HashingStrategies.fromFunction(s -> s.length()))
.makeString()
, is("hoge, fugafuga")
);
##並べ替え
MutableList<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo");
assertThat(
hogeList
.sortThis()
.makeString()
, is("fuga, hoge, piyo")
);
並び替えの基準を指定したり、降順にする事も可能。
MutableList<String> hogeList = Lists.mutable.of("hogehoge", "fuga", "piyopi");
assertThat(
hogeList
.sortThisBy(s -> s.length())
.reverseThis()
.makeString()
, is("hogehoge, piyopi, fuga")
);
##繰り返し
繰り返し処理をした後、さらに処理を続けて書きたいなら、tap
もあるぞ。
ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo");
hogeList
.each(s ->
System.out.println(s)
);
//実行結果
//hoge
//fuga
//piyo
forEachWithIndexなら、index付きでループさせる事ができます。
ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo");
hogeList
.forEachWithIndex((string, index) ->
System.out.println(String.valueOf(index).concat(string))
);
//実行結果
//0hoge
//1fuga
//2piyo
##集計
groupByで、指定した値ごとにグループ化できます。
ListMultimap
という型で返ってきて、様々な方法で取り出す事ができるが、私はkeyMultiValuePairsView()
メソッドでPair
(後述)にして使うのが好きです。
ListIterable<String> hogeList = Lists.mutable.of("hoge", "hogera", "fuga", "fugafuga", "piyo", "piyopiyo");
hogeList
.groupBy(s -> s.length())
.keyMultiValuePairsView()
.each(p ->{
System.out.println(p.getOne() + " -> " + p.getTwo());
});
//実行結果
//4 -> [hoge, fuga, piyo]
//6 -> [hogera]
//8 -> [fugafuga, piyopiyo]
##合計
ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo");
assertThat(
hogeList
.sumOfInt(s -> s.length())
, is(12L)
);
##要素を1つだけ取得したい
###最初の1つ
要素が1つもない場合は、nullが返される。
ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo");
assertThat(
hogeList
.select(s -> s.contains("g"))
.getFirst()
, is("hoge")
);
###最後の1つ
こちらも、要素が1つもない場合は、nullが返される。
ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo");
assertThat(
hogeList
.select(s -> s.contains("g"))
.getLast()
, is("fuga")
);
###1つしかないはずの要素
select
等で要素を1つだけに絞り込めているはずであれば、getOnlyを使おう。
要素が1つでない場合はIllegalStateExceptionが投げられる。
ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo");
assertThat(
hogeList
.select(s -> s.contains("i"))
.getOnly()
, is("piyo")
);
#標準Collectionからの変換
プロジェクトで使っているフレームワーク等で、java.util.List
等の標準Collectionが使われている事はよくあります。
このような場合、Eclipse Collectionsを使いたくなると、下記のように一旦ofAll
等でEclipse Collectionsの型に変換する事になりますが、数が多くなってくるとちょい邪魔です。
List<String> hogeList = Arrays.asList("konna", "fuuni", "shiteita");
ImmutableList<String> fugaList = Lists.immutable.ofAll(hogeList);
fugaList.select(s -> s.length > 4);
こんな時、ListAdapter
を使えば一発でeclipse collestionsのメソッドを使えます。
List
でなくArray
なら、ArrayAdapter
もあるぞ。
List<String> hogeList = Arrays.asList("kore", "de", "yokatta");
ListAdapter.adapt(hogeList)
.select(s -> s.length > 4);
あとは、adaptすら不要なListIterate
やArrayIterate
もある。
List<String> hogeList = Arrays.asList("adapt", "mo", "shinai");
ListIterate.select(hogeList, s -> s.length > 4);
#その他データセット
##2つの値をセットで保持したい
keyとvalueのペアでデータを持ちたい、みたいな時に使う。
Tuples
から、2種類のインスタンスが生成できる。
###Pair
それぞれ異なる型の場合はこちら。
Pair<String, Object> keyValuePair = Tuples.pair("key", value);
String key = keyValuePair.getOne();
Object value = keyValuePair.getTwo();
###Twin
同じ型の値を扱う場合は、こちらが使える。
Twin<String> keyValueTwin = Tuples.twin("key", "valiue");
String key = keyValueTwin.getOne();
String value = keyValueTwin.getTwo();
#例外処理
lambdaの中で検査例外が発生してしまったら、せっかく簡潔に書けていたコードが台無しになってしまう。
そんな時は、下記を静的インポートし、throwingメソッドを使う。
import static org.eclipse.collections.impl.block.factory.Procedures.*;
import static org.eclipse.collections.impl.block.factory.Functions.*;
import static org.eclipse.collections.impl.block.factory.Predicates.*;
throwingの中で例外が発生すると、RuntimeExceptionにラップして投げ直してくれる。
これで簡潔に書けるようになった。
hogeList
.each(throwing(Fuga::piyo)
;