11
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-07-12

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

またソートを例にします。
#ソートをラムダ式1に置き換える

ラムダ使わない
	/**
	 * 大文字小文字無視したソート
	 */
	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だと、

ラムダ式(メソッド参照)
	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回実行してみます。

ラムダ使わない
	/**
	 * 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
	}
ラムダ式(メソッド参照)
	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をラムダ式じゃない記述に置き換える

ラムダ使わない
	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
その2:Java8が好きになる話(StreamAPIの話はしない) その2 Optional#map
その3:Java8が好きになる話(StreamAPIの話はしない) その3 インターフェースのデフォルト実装

  1. というかメソッド参照 2 3 4 5 6

11
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?