Java8が好きになる話（StreamAPIの話はしない） その4 ラムダ式のインスタンス

今回はラムダ式についてです。
（もうラムダ・メソッド参照に関わらないネタが思い付かないです。）
ラムダ式の書き方については他で紹介してるページを参考にしてもらうとして、
ここではラムダ式[^1]を書いた場合どういうインスタンスが生成されるか確認しておきたいです。
参考：http://www.oracle.com/technetwork/jp/articles/java/architect-lambdas-part2-2081439-ja.html

またソートを例にします。
#ソートをラムダ式[^1]に置き換える
```java:ラムダ使わない
	/**
	 * 大文字小文字無視したソート
	 */
	public static void sort() {
		List<String> list = new ArrayList<>(Arrays.asList("C", "b", "A"));
		Collections.sort(list, new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				return o1.compareToIgnoreCase(o2);
			}
		});
		System.out.println(list);//[A, b, C]
	}
```
がラムダ式[^1]だと、

```java:ラムダ式（メソッド参照）
	public static void sort() {
		List<String> list = new ArrayList<>(Arrays.asList("C", "b", "A"));
		list.sort(String::compareToIgnoreCase);
		System.out.println(list);//[A, b, C]
	}
```
わー短く書けるね。って話ではなくてですね、
この2つがどういうインスタンス生成されるか確認したいという話です。

#Comparatorのインスタンス数を確認してみる
インスタンスを確認するためComparatorを変数に一旦格納するのと、
これらのロジックを10回実行してみます。

```java:ラムダ使わない
	/**
	 * Comparatorのインスタンス生成数確認
	 */
	public static void sortAndCheck() {
		Set<Comparator<String>> set = new HashSet<>();
		for (int i = 0; i < 10; i++) {
			List<String> list = new ArrayList<>(Arrays.asList("C", "b", "A"));
			Comparator<String> comparator = new Comparator<String>() {
				@Override
				public int compare(String o1, String o2) {
					return o1.compareToIgnoreCase(o2);
				}
			};
			set.add(comparator);
			Collections.sort(list, comparator);
			System.out.println(i + 1 + " " + list);
		}
		System.out.println("count:" + set.size());//set.size()は10
	}
```
```java:ラムダ式（メソッド参照）
	public static void sortAndCheck() {
		Set<Comparator<String>> set = new HashSet<>();
		for (int i = 0; i < 10; i++) {
			List<String> list = new ArrayList<>(Arrays.asList("C", "b", "A"));
			Comparator<String> comparator = String::compareToIgnoreCase;
			set.add(comparator);
			Collections.sort(list, comparator);
			System.out.println(i + 1 + " " + list);
		}
		System.out.println("count:" + set.size());//set.size()は1
	}
```

で実行するとラムダ使わないほうはインスタンスが10個生成されてしまいます。
それに比べてラムダ式[^1]の方は1個だけです。

つまりラムダ使わずにラムダ式[^1]の方を再現すると正しくは下記のようになります。

#ラムダ式[^1]をラムダ式じゃない記述に置き換える
```java:ラムダ使わない
	private static final Comparator<String> comparatorIgnoreCase = new Comparator<String>() {
		@Override
		public int compare(String o1, String o2) {
			return o1.compareToIgnoreCase(o2);
		}
	};

	/**
	 * 大文字小文字無視したソート
	 */
	public static void sort() {
		List<String> list = new ArrayList<>(Arrays.asList("C", "b", "A"));
		Collections.sort(list, comparatorIgnoreCase);
		System.out.println(list);//[A, b, C]
	}

	/**
	 * Comparatorのインスタンス生成数確認
	 */
	public static void sortAndCheck() {
		Set<Comparator<String>> set = new HashSet<>();
		for (int i = 0; i < 10; i++) {
			List<String> list = new ArrayList<>(Arrays.asList("C", "b", "A"));
			Comparator<String> comparator = comparatorIgnoreCase;
			set.add(comparator);
			Collections.sort(list, comparator);
			System.out.println(i + 1 + " " + list);
		}
		System.out.println("count:" + set.size());//set.size()は1
	}
```

ここまで書くぐらいならラムダ式書いた方が明らかにスマートですね。


#まとめ
ラムダ式は単純置き換え元よりは明らかにインスタンスが節約できるという話でした。

※今回はインスタンス節約できる例で書いただけで必ずそうなるわけではありません。
　条件まとめるのめんどくさいので書きませんが、基本的にはやっぱり節約できるはずです。

---

その5につづく。（ネタ考えます）

その1：[Java8が好きになる話（StreamAPIの話はしない） その1 Map#computeIfAbsentとList#sort](http://qiita.com/ota-meshi/items/31f36d38d4da8fce3c57)
その2：[Java8が好きになる話（StreamAPIの話はしない） その2 Optional#map](http://qiita.com/ota-meshi/items/dbdd592b613e38b7a4bb)
その3：[Java8が好きになる話（StreamAPIの話はしない） その3 インターフェースのデフォルト実装](http://qiita.com/ota-meshi/items/43811647af9daed4d21e)
[^1]: というかメソッド参照