Stream APIのallMatch()、anyMatch()、noneMatch()メソッドを使ってみた

こんにちは。「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

以上、参考になれば幸いです。

スポンサーリンク