こんにちは。「Javaを復習する初心者」です。今回はStream APIの以下の3つのメソッドを使ってみました。
- boolean allMatch(Predicate<? super T> predicate)
- boolean anyMatch(Predicate<? super T> predicate)
- boolean noneMatch(Predicate<? super T> predicate)
ArrayListにいくつか要素を追加して、上記の3つのメソッドを試してみました。
準備
ArrayListの要素のクラスとして、以下のクラスを作成しました。
Personクラス
public class Person {
private String name;
private double height;
private double weight;
public Person(String name, double height, double weight) {
this.name = name;
this.height = height;
this.weight = weight;
}
public String getName() {
return name;
}
public double getHeight() {
return height;
}
public double getWeight() {
return weight;
}
}
メンバ変数に名前、身長、体重を持つクラスです。サンプルプログラムでは、ArrayListの要素をこのクラスに指定して、インスタンスをいくつか追加します。その後、ArrayListのストリームを取得して、allMatch()などのメソッドを呼び出します。
具体な使い方
allMatch()、anyMatch()、noneMatch()の引数にはboolean値関数を指定します。また、これら3つのメソッドはboolean値を返却します。
引数はラムダ式を記述することができるので、今回はその記述方法を使います。
以下、それぞれを使ってみました。
allMatch()
簡単に言うと、引数に記述したラムダ式が全部の要素でtrueを返却した場合、allMatch()メソッドはtrueを返却します。
例えば、上記で定義したPersonを要素に持つArrayListクラスの変数listを定義したとします。
以下のサンプルプログラムでは、「全ての要素でheightの値が特定の数値より大きいか」をチェックしています。
allMatch()を使った例
import java.util.ArrayList;
public class Sample0001 {
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("Name001", 165.1, 52.1));
list.add(new Person("Name002", 166.1, 62.2));
list.add(new Person("Name003", 167.1, 72.3));
list.add(new Person("Name004", 168.1, 82.4));
list.add(new Person("Name005", 169.1, 92.5));
boolean flg = false;
flg = list.stream().allMatch(person
-> person.getHeight() > 165.1);
System.out.println("height > 165.1");
System.out.println(flg);
flg = list.stream().allMatch(person
-> person.getHeight() > 165.0);
System.out.println("height > 165.0");
System.out.println(flg);
}
}
結果
height > 165.1
false
height > 165.0
true
最初のallMatch()メソッドの引数のラムダ式は、「heightが165.1より大きい」という条件式の結果を返却しています。ラムダ式は各要素に対して、実行されます。返却される値は以下のようになります。
name | height | weight | ラムダ式が返却する値 |
---|---|---|---|
Name001 | 165.1 | 52.1 | false |
Name002 | 166.1 | 62.2 | true |
Name003 | 167.1 | 72.3 | true |
Name004 | 168.1 | 82.4 | true |
Name005 | 169.1 | 92.5 | true |
「Name001」の要素に対して、条件式「person.getHeight() > 165.1」がfalseです。allMatch()メソッドがtureを返却するには、「全員に対して、引数のラムダ式の戻り値がtrueを返却」という動作をしなくてはなりません。今回は「Name001」でラムダ式がfalseを返却しているため、allMatch()メソッドはfalseを返却します。
2番目のallMatch()の引数のラムダ式では、「heightが165.0より大きい」という条件式の結果を返却しています。すべての要素でperson.heightの値は165.0より大きいので、ラムダ式は全ての要素でtrueを返却します。その結果、allMatch()メソッドはtrueを返却します。
anyMatch()
簡単に言うと、引数に記述したラムダ式が少なくとも一つの要素でtrueを返却した場合、anyMatch()メソッドはtrueを返却します。
以下のサンプルプログラムでは、「heightが特定の数値より大きい」という要素が少なくとも一つ存在するかをチェックしています。
anyMatch()を使った例
import java.util.ArrayList;
public class Sample0002 {
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("Name001", 165.1, 52.1));
list.add(new Person("Name002", 166.1, 62.2));
list.add(new Person("Name003", 167.1, 72.3));
list.add(new Person("Name004", 168.1, 82.4));
list.add(new Person("Name005", 169.1, 92.5));
boolean flg = false;
flg = list.stream().anyMatch(person
-> person.getHeight() > 169.0);
System.out.println("height > 169.0");
System.out.println(flg);
flg = list.stream().anyMatch(person
-> person.getHeight() > 169.1);
System.out.println("height > 169.1");
System.out.println(flg);
}
}
結果
height > 169.0
true
height > 169.1
false
最初のanyMatch()メソッドの引数のラムダ式は、「Name005」の要素の場合でtrueを返却します。少なくとも一つの要素でラムダ式がtrueを返却したため、anyMatch()メソッドはtrueを返却します。
2番目のanyMatch()メソッドの引数のラムダ式は、「Name001」から「Name005」の要素の場合でfalseを返却します。全部の要素の場合でラムダ式がfalseを返却したため、anyMatch()メソッドはfalseを返却します。
noneMatch()メソッド
簡単に言うと、引数に記述したラムダ式が全ての要素でfalseを返却した場合、anyMatch()メソッドはtrueを返却します。
以下のサンプルプログラムでは、「heightが特定の数値より大きい」という要素が存在しないことをチェックしています。
noneMatch()を使った例
import java.util.ArrayList;
public class Sample0003 {
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("Name001", 165.1, 52.1));
list.add(new Person("Name002", 166.1, 62.2));
list.add(new Person("Name003", 167.1, 72.3));
list.add(new Person("Name004", 168.1, 82.4));
list.add(new Person("Name005", 169.1, 92.5));
boolean flg = false;
flg = list.stream().noneMatch(person
-> person.getHeight() > 169.0);
System.out.println("height > 169.0");
System.out.println(flg);
flg = list.stream().noneMatch(person
-> person.getHeight() > 169.1);
System.out.println("height > 169.1");
System.out.println(flg);
}
}
結果
height > 169.0
false
height > 169.1
true
最初のnoneMatch()メソッドの引数のラムダ式は、「Name001」から「Name004」の要素の場合でfalseを返却します。「Name005」の要素では、trueを返却します。そのため、noneMatch()メソッドはfalseを返却します。
2番目のnoneMatch()メソッドの引数のラムダ式は、「Name001」から「Name005」の要素の場合でfalseを返却します。全ての要素の場合でラムダ式がfalseを返却したため、noneMatch()メソッドはtrueを返却します。
複数の条件を指定してみる
ラムダ式の返却値の条件式の個所で論理演算子を使うことで、複数の条件を指定することができます。
例えば、以下のような記述ができます。
ソース
flg = list.stream().allMatch(person
-> person.getHeight() > 165.0 && person.getWeight() > 52.0);
上記では、身長の条件と体重の条件を組み合わせているということです。
複雑な処理を指定してみる
ラムダ式で複雑な処理を使いたい場合、波括弧を使います。
例えば、以下のような記述ができます。
ソース
flg = list.stream().allMatch(person -> {
double h = person.getHeight();
double w = person.getWeight();
return h > 2.0 * w;
});
上記では、身長と体重をローカル変数に格納して、条件式を作っています。
要素が空の場合
ArrayListが空の場合に、list.stream()はエラーになりません。ストリームの要素の個数が0という状態です。
上記のストリームに対して、allMatch()、anyMatch()、noneMatch()を呼び出しても、エラーは発生しません。
以下のサンプルプログラムでは、ArrayListが空の場合で、各メソッドを呼び出しています。
要素が空の場合
import java.util.ArrayList;
public class Sample0006 {
public static void main(String[] args) {
ArrayList<Person> list = new ArrayList<>();
System.out.println("要素の個数");
System.out.println(list.stream().count());
System.out.println("-----------------");
boolean flg = false;
flg = list.stream().allMatch(person
-> person.getHeight() > 165.1);
System.out.println("allMatch");
System.out.println(flg);
System.out.println("-----------------");
flg = list.stream().anyMatch(person
-> person.getHeight() > 165.1);
System.out.println("anyMatch");
System.out.println(flg);
System.out.println("-----------------");
flg = list.stream().noneMatch(person
-> person.getHeight() > 165.1);
System.out.println("noneMatch");
System.out.println(flg);
}
}
結果
要素の個数
0
-----------------
allMatch
true
-----------------
anyMatch
false
-----------------
noneMatch
true
上記の結果が出力されました。
Java SE 12のAPIリファレンスを見ると、メソッドの説明に、ストリームが空の場合の説明があります。
allMatch()の説明には以下のように記載があります。
ストリームが空の場合、trueが返され、述語は評価されません。
anyMatch()の説明には以下のように記載があります。
ストリームが空の場合、falseが返され、述語は評価されません。
noneMatch()の説明には以下のような説明があります。
ストリームが空の場合、trueが返され、述語は評価されません。
まとめると、要素が空の場合、以下の値が返却されます。
メソッド | ストリームが空の場合 |
---|---|
allMatch | true |
anyMatch | false |
noneMatch | true |
以上、参考になれば幸いです。