9
9

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のStreamを使ってみる

Last updated at Posted at 2014-07-11

Java8ではラムダ式やインターフェースのデフォルト値等かなり仕様が変更/追加されました。今回はその中の一つである Stream とやらを使ったプロパティファイルリーダーを組んでみたいと思います。

#まずStreamってなんぞや
Streamというのは、従来配列やList等で表現されていた複数のオブジェクトの集合体に対する操作を分かりやすく記述出来るようにするツールと言えます。

#簡単な使い方
Stream オブジェクトを取得するにはstream()メソッドを用います。これはJava8であればあれば便利と思われる場所には付いています。

Stream<String> s = Stream.of("a", "b", "c");
s.forEach(x -> {
    System.out.println(x);
});

これは文字列のリストからStreamを生成し、順に表示させた例です。中にある見慣れないx -> {という構文は ラムダ式 と呼ばれるJava8でStreamと同じく追加された新機能です。
ここでforEachというメソッドが登場しました。これは名前の通り引数に指定された処理を順に適用していくメソッドで、従来の拡張forに相当します。
このように、Streamを利用することで流れ作業のようにオブジェクトを処理することが出来るようになり、コードが見やすくなります。

#実際のコード
実際にStreamを利用したプロパティファイルリーダーのコードを見てみましょう。次のようになります。

PropertyReader.java
package xyz.n6g;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Map;
import java.util.stream.Collectors;

public class PropertyReader {

	private File file;
	private Map<String, String> props = null;

	public PropertyReader(String par1FileName) {
		this(new File(par1FileName));
	}

	public PropertyReader(File par1File) {
		this.file = par1File;
		load();
	}

	public String get(String par1Key) {
		return props.get(par1Key);
	}

	public void load() {
		try(BufferedReader br = new BufferedReader(new FileReader(this.file))) {
			props = br.lines().filter(x -> {
				return x.matches("(\\w+)\\s*=\\s*(.+)$");
			}).collect(
					Collectors.toMap(x -> {
						return ((String)x).split("=")[0].trim();
					}, x -> {
						return ((String)x).split("=")[1].trim();
					})
			);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}

	public void show() {
		System.out.println(props);
	}
}

流れを追うこと自体は難しく無いと思います。loadメソッドについて見て行きましょう。

まず冒頭のtry-with-resourceBufferedReaderを生成しています。
次に、br.lines()というメソッドからの一連の流れが見えます。これはBufferedReaderからStreamを取得し、そのStreamに対して処理を施して最終的にMapに落としこんでいます。

まずbr.lines()で行ごとに切り分けられたStreamを取得し、次にfilterというメソッドにラムダ式を渡しています。これはメソッド名の通り「引数に与えられた判定ロジックの結果から値を取捨選択するメソッド」です。ここでは正規表現でaaa = bbbのような形式の文字列のみを読むように指定しています。
次に、collectというメソッドを呼び出しています。これは「Streamで流れてきたオブジェクトをそれぞれ引数に与えられた"コレクター"に渡し、特定の形式に落としこむメソッド」です。ここでは、標準で用意されているCollectors.toMapを利用しています。ここで更に指定しているラムダ式は2つあり、それぞれマップのキーと値に相当しています。つまりこの場合だと「=で切り分けた0番目をキーに、1番目を値にし、それぞれの前後に存在する空白を削除する」という処理をしています。
ここで切り分けられてMapに落とし込まれたものが最終的な返り値となり、propsフィールドに格納されます。

#終わりに
Streamは今までの繰り返し処理の大半を綺麗に書きなおすことが出来ると思います。これを機会に学習してみて下さい。
また、Qiita初投稿だったので体裁なども見苦しい点があるとは思いますが見逃してやって下さい(

9
9
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
9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?