StreamExの概要
1. 概要
Java 8の最もエキサイティングな機能の1つは、Stream APIです。これは、簡単に言えば、要素のシーケンスを処理するための強力なツールです。
StreamExは、パフォーマンスの向上とともに、標準のStreamAPIに追加機能を提供するライブラリです。
主な機能は次のとおりです。
-
日常のタスクを行うより短くて便利な方法
-
元のJDKStreamsとの100%の互換性
-
並列処理の使いやすさ:すべての新機能は、可能な限り並列ストリームを活用します
-
パフォーマンスと最小限のオーバーヘッド。 StreamExで、標準のStream,と比較して少ないコードでタスクを解決できる場合は、通常の方法よりも大幅に遅くなることはありません(場合によってはさらに速くなります)。
このチュートリアルでは、StreamExAPIのいくつかの機能を紹介します。
2. サンプルのセットアップ
StreamExを使用するには、次の依存関係をpom.xmlに追加する必要があります。
one.util
streamex
0.6.5
ライブラリの最新バージョンはMaven Centralにあります。
このチュートリアルでは、単純なUserクラスを使用します。
public class User {
int id;
String name;
Role role = new Role();
// standard getters, setters, and constructors
}
そして、単純なRoleクラス:
public class Role {
}
3. コレクターショートカットメソッド
Streamsの最も一般的な端末操作の1つは、collect操作です。これにより、Stream要素を選択したコレクションに再パッケージ化できます。
問題は、単純なシナリオではコードが不必要に冗長になる可能性があることです。
users.stream()
.map(User::getName)
.collect(Collectors.toList());
3.1. コレクションへの収集
現在、StreamExでは、List、Set, Map, InmutableList,などが必要であることを指定するためにCollectorを指定する必要はありません。
List userNames = StreamEx.of(users)
.map(User::getName)
.toList();
Streamから要素を取得してコレクションに配置するよりも複雑な処理を実行する場合は、collect操作をAPIで引き続き使用できます。
3.2. 高度なコレクター
もう1つの省略形はgroupingByです:
Map> role2users = StreamEx.of(users)
.groupingBy(User::getRole);
これにより、メソッドリファレンスで指定されたキータイプのMapが生成され、SQLのgroupby操作に似たものが生成されます。
プレーンなStream APIを使用して、次のように記述する必要があります。
Map> role2users = users.stream()
.collect(Collectors.groupingBy(User::getRole));
Collectors.joining():についても同様の省略形があります。
StreamEx.of(1, 2, 3)
.joining("; "); // "1; 2; 3"
Stream aのすべての要素を取得すると、それらすべてを連結するStringが生成されます。
4. 要素の追加、削除、選択
一部のシナリオでは、we’ve got a list of objects of different types, and we need to filter them by type:
List usersAndRoles = Arrays.asList(new User(), new Role());
List roles = StreamEx.of(usersAndRoles)
.select(Role.class)
.toList();
この便利な操作でWe can add elements to the start or end of our*Stream*,:
List appendedUsers = StreamEx.of(users)
.map(User::getName)
.prepend("(none)")
.append("LAST")
.toList();
We can remove unwanted null elements using nonNull()およびStreamをIterableとして使用します。
for (String line : StreamEx.of(users).map(User::getName).nonNull()) {
System.out.println(line);
}
5. 数学演算とプリミティブ型のサポート
StreamExは、この自明の例でわかるように、プリミティブ型のサポートを追加します。
short[] src = {1,2,3};
char[] output = IntStreamEx.of(src)
.map(x -> x * 5)
.toCharArray();
次に、double要素の配列を順序付けられていない方法で取得しましょう。 各ペアの差で構成される配列を作成します。
pairMapメソッドを使用して、この操作を実行できます。
public double[] getDiffBetweenPairs(double... numbers) {
return DoubleStreamEx.of(numbers)
.pairMap((a, b) -> b - a)
.toArray();
}
6. 地図操作
6.1. キーによるフィルタリング
もう1つの便利な機能は、MapからStreamを作成し、それらが指す値を使用して要素をフィルタリングする機能です。
この場合、null以外のすべての値を取得します。
Map nameToRole = new HashMap<>();
nameToRole.put("first", new Role());
nameToRole.put("second", null);
Set nonNullRoles = StreamEx.ofKeys(nameToRole, Objects::nonNull)
.toSet();
6.2. キーと値のペアの操作
EntryStreamインスタンスを作成することで、キーと値のペアを操作することもできます。
public Map> transformMap(
Map> role2users) {
Map> users2roles = EntryStream.of(role2users)
.flatMapValues(List::stream)
.invert()
.grouping();
return users2roles;
}
特別な操作EntryStream.ofは、Mapを受け取り、それをKey-ValueオブジェクトのStreamに変換します。 次に、flatMapValues操作を使用して、ロールのリストを単一値のStreamに変換します。
次に、キーと値のペアをinvertして、Userクラスをキーにし、Roleクラスを値にすることができます。
そして最後に、grouping操作を使用して、マップを受信したマップの反転に変換できます。すべて4つの操作で済みます。
6.3. キーと値のマッピング
キーと値を個別にマッピングすることもできます。
Map mapToString = EntryStream.of(users2roles)
.mapKeys(String::valueOf)
.mapValues(String::valueOf)
.toMap();
これにより、キーまたは値を別の必要なタイプにすばやく変換できます。
7. ファイル操作
StreamExを使用すると、ファイルを効率的に読み取ることができます。つまり、一度に完全なファイルをロードする必要はありません。 大きなファイルを処理するときに便利です。
StreamEx.ofLines(reader)
.remove(String::isEmpty)
.forEach(System.out::println);
remove()メソッドを使用して、空の行を除外していることに注意してください。
ここで注意すべき点は、StreamExはファイルを自動的に閉じないということです。 したがって、不要なメモリオーバーヘッドを回避するために、ファイルの読み取りと書き込みの両方の機会で手動で閉じる操作を実行することを忘れないでください。
8. 結論
このチュートリアルでは、StreamExと、さまざまなユーティリティについて学習しました。 通過することがもっとたくさんあります-そして彼らは便利なチートシートhereを持っています。
いつものように、完全なソースコードはover on GitHubで利用できます。