16
17

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の話はしない) その2 Optional#map

Last updated at Posted at 2015-07-11

StreamAPIも大好きですよ。

前回はラムダもなるべく推さないように書いていたつもりですがさすがに今回は使います。

#Optional#map
Optionalは、nullかもしれない返り値を示すやつですが、
返り値以外で使っても便利だと思うのです。

##数珠つなぎなnullチェック

準備
	public static class Struct1 {
		private final Struct2 value;

		public Struct1(Struct2 value) {
			this.value = value;
		}

		public Struct2 getValue() {
			return this.value;
		}
	}

	public static class Struct2 {
		private final Struct3 value;

		public Struct2(Struct3 value) {
			this.value = value;
		}

		public Struct3 getValue() {
			return this.value;
		}
	}

	public static class Struct3 {
		private final String value;

		public Struct3(String value) {
			this.value = value;
		}

		public String getValue() {
			return this.value;
		}
	}

	private static Struct1 data1 = new Struct1(new Struct2(new Struct3("DATA")));
	private static Struct1 data2 = new Struct1(new Struct2(null));
	private static Struct1 data3 = null;

	public static void main(String[] args) {
		System.out.println(getStruct3Value(data1));//DATA
		System.out.println(getStruct3Value(data2));//null
		System.out.println(getStruct3Value(data3));//null
	}
java7以前
	/**
	 * Struct3のvalueを取得。途中nullだったらnullを返す。
	 */
	public static String getStruct3Value(Struct1 struct1) {
		if (struct1 == null) {
			return null;
		}
		Struct2 struct2 = struct1.getValue();
		if (struct2 == null) {
			return null;
		}
		Struct3 struct3 = struct2.getValue();
		if (struct3 == null) {
			return null;
		}
		return struct3.getValue();
	}

みたいなnullチェックの嵐を書くような場合、Optional#mapが使えます。

java8Optional
	public static String getStruct3Value(Struct1 struct1) {
		Optional<Struct1> opt = Optional.ofNullable(struct1);
		return opt.map(Struct1::getValue)
				.map(Struct2::getValue)
				.map(Struct3::getValue)
				.orElse(null);
	}

と。スッキリしますね。

数珠つなぎなnullチェック嵐じゃなくて、次のようなnullチェック嵐でも使えます。

##複数個所でのnullチェック

準備
	public static class Foo {
		private final String value1;
		private final String value2;

		public Foo(String value1, String value2) {
			this.value1 = value1;
			this.value2 = value2;
		}

		public String getValue1() {
			return this.value1;
		}

		public String getValue2() {
			return this.value2;
		}
	}
java7以前
	/**
	 * value1のlenthを取得。fooがnullだったら0をかえす
	 */
	public static int getValue1Length(Foo foo) {
		if (foo != null) {
			if (foo.getValue1() != null) {
				return foo.getValue1().length();
			}
		}
		return 0;
	}
	/**
	 * value2のlenthを取得。fooがnullだったら0をかえす
	 */
	public static int getValue2Length(Foo foo) {
		if (foo != null) {
			if (foo.getValue2() != null) {
				return foo.getValue2().length();
			}
		}
		return 0;
	}

っていうような、数ヶ所のnullチェックの嵐がある場合も、
Optionalを使って、

java8Optional
	public static int getValue1Length(Optional<Foo> foo) {
		return foo.map(Foo::getValue1)
				.map(String::length)
				.orElse(0);
	}

	public static int getValue2Length(Optional<Foo> foo) {
		return foo.map(Foo::getValue2)
				.map(String::length)
				.orElse(0);
	}

とやると簡潔になりますしミスが少なくなりそうで便利です。

Optional使いたくなりませんか。

#おまけ
で、本気でOptional使おうと思うと実はなかなか難しかったりすると思います。

Optionalはnullかもしれない値を返すということなので、nullになりえない値はOptionalじゃないってことですよね。
すでにあるプログラムの返り値はOptionalじゃないわけですから、ほうっておいたらどちらなのかわかりませんね。
全部書き換えるのは現実的じゃないですし、そもそもJavaさんのMap#getもOptional返してくれませんし、それに相当するメソッドもありません。

現実的にはたまにOptionalつかって便利にこなす位がちょうどいいんじゃないかなーなんて勝手に思ってます。


その3に続く。

その1:Java8が好きになる話(StreamAPIの話はしない) その1 Map#computeIfAbsentとList#sort

16
17
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
16
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?