Eclipse Collectionsチートシート

# 概要
Eclipse Collections自体の解説については、他に良い記事がたくさんあると思うので、ここでは「〇〇がしたい」と思った時にすぐ参照できるリファレンスとしてアップします。
とりあえず、よく使うものをリストアップしてみましたが、他に出てきたら追加するかもしれません。
*※ほとんどList系しか書いてません。*

# 環境
Ver.8.0.0
*すみません、普段仕事で使っているバージョンという事で、若干古めです。*

```pom.xml
		<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>
```

# 初期化
## 空のリスト

```java:empty
Lists.mutable.empty();
```
これ以降、特に断りを入れませんが、mutable(MutableList)のほかにimmutable(ImmutableList)も使えます。
ImmutableListは、add等のメソッドが存在せず、変更不可になっています。
*※ソート系など、一部MutableListでしか使えないメソッドがありますので、ご注意ください*

```java:empty
Lists.immutable.empty();
```

## まとめて初期化

```java:of
Lists.mutable.of(first, second, third);
```

## Iterableを元に初期化
java.util.List等をImmutableList等に変換できます。

```java:ofall
Lists.immutable.ofAll(hogeList);
```

# 頻出パターン集
## 条件を満たす要素だけを取り出す
```java:select
		ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo");
		assertThat(
				hogeList
					.select(s -> s.contains("g"))
					.makeString()
				, is("hoge, fuga")
			);
```

## 条件を満たす要素があるかどうか確認したい
`anySatisfy`は、条件を満たす要素が1つでもあれば、trueを返します。

```java:anySatisfy
		ListIterable<String> hogeList = Lists.mutable.of("hoge", null, "fuga");
		assertThat(
				hogeList.anySatisfy(s -> s == null)
				, is(true)
			);
```
## 全ての要素が条件を満たさない事を確認したい
`noneSatisfy`は、条件を満たす要素が1つもなければ、trueを返します。

```java:noneSatisfy
		ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo");
		assertThat(
				hogeList.noneSatisfy(s -> s.equals("hogera"))
				, is(true)
			);
```
## 1つでも条件を満たす要素があれば取得したい
`detect`は、条件を満たす要素のうち、最初の1つだけを取り出します。

```java:detect
		ListIterable<String> hogeList = Lists.mutable.of(null, "hoge", "fuga");
		assertThat(
				hogeList.detect(s -> s != null).toString()
				, is("hoge")
			);
```

## 要素を変換し、新しいListにする
```java:collect
		ListIterable<String> hogeList = Lists.mutable.of("hogehoge", "fuga", "piyopi");
		assertThat(
				hogeList
					.collect(s -> s.length())
					.makeString()
				, is("8, 4, 6")
			);
```
## 重複排除
重複を排除し、ユニークな要素のみ残す。

```java:distinct
		ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo", "fuga", "piyo");
		assertThat(
				hogeList
					.distinct()
					.makeString()
				, is("hoge, fuga, piyo")
			);
```

ユニークと判断する基準を指定する事も可能。この時、結果のリストに残るのは、重複している要素のうち最初の1つのみ。

```java:distinct
		ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo", "fugafuga", "piyopiyo");
		assertThat(
				hogeList
					.distinct(HashingStrategies.fromFunction(s -> s.length()))
					.makeString()
				, is("hoge, fugafuga")
			);
```

## 並べ替え

```java:sortThis
		MutableList<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo");
		assertThat(
				hogeList
					.sortThis()
					.makeString()
				, is("fuga, hoge, piyo")
			);
```

並び替えの基準を指定したり、降順にする事も可能。

```java:sortThisBy
		MutableList<String> hogeList = Lists.mutable.of("hogehoge", "fuga", "piyopi");
		assertThat(
				hogeList
					.sortThisBy(s -> s.length())
					.reverseThis()
					.makeString()
				, is("hogehoge, piyopi, fuga")
			);
```

## 繰り返し
繰り返し処理をした後、さらに処理を続けて書きたいなら、`tap`もあるぞ。

```java:each
		ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo");
		hogeList
			.each(s ->
				System.out.println(s)
			);
		//実行結果
		//hoge
		//fuga
		//piyo
```
forEachWithIndexなら、index付きでループさせる事ができます。

```java:forEachWithIndex
		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`(後述)にして使うのが好きです。

```java:groupBy
		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]
```

## 合計

```java:sumOfInt
		ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo");
		assertThat(
				hogeList
					.sumOfInt(s -> s.length())
				, is(12L)
			);
```

## 要素を1つだけ取得したい
### 最初の1つ
要素が1つもない場合は、nullが返される。

```java:getFirst
		ListIterable<String> hogeList = Lists.mutable.of("hoge", "fuga", "piyo");
		assertThat(
				hogeList
					.select(s -> s.contains("g"))
					.getFirst()
				, is("hoge")
			);
```

### 最後の1つ
こちらも、要素が1つもない場合は、nullが返される。

```java:getLast
		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が投げられる。

```java:getOnly
		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の型に変換する事になりますが、数が多くなってくるとちょい邪魔です。

```java:こんなふうにしがち
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`もあるぞ。

```java:これでよかった
List<String> hogeList = Arrays.asList("kore", "de", "yokatta");
ListAdapter.adapt(hogeList)
           .select(s -> s.length > 4);
```

あとは、adaptすら不要な`ListIterate`や`ArrayIterate`もある。

```java:ListIterate
List<String> hogeList = Arrays.asList("adapt", "mo", "shinai");
ListIterate.select(hogeList, s -> s.length > 4);
```
# その他データセット
## 2つの値をセットで保持したい
keyとvalueのペアでデータを持ちたい、みたいな時に使う。
`Tuples`から、2種類のインスタンスが生成できる。
### Pair<T1, T2>
それぞれ異なる型の場合はこちら。

```java:Pair
Pair<String, Object> keyValuePair = Tuples.pair("key", value);
String key = keyValuePair.getOne();
Object value = keyValuePair.getTwo();
```

### Twin<T>
同じ型の値を扱う場合は、こちらが使える。

```java:Twin
Twin<String> keyValueTwin = Tuples.twin("key", "valiue");
String key = keyValueTwin.getOne();
String value = keyValueTwin.getTwo();
```

# 例外処理
lambdaの中で検査例外が発生してしまったら、せっかく簡潔に書けていたコードが台無しになってしまう。
そんな時は、下記を静的インポートし、throwingメソッドを使う。

```java
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にラップして投げ直してくれる。
これで簡潔に書けるようになった。

```java:throwing
		hogeList
			.each(throwing(Fuga::piyo)
			;

```