ytterrr
ytterrr

Reputation: 3256

Method reference and chained predicate

I'm trying to compactify my code with method references. Here is a line that I'm trying to improve:

assertThat("only true & false strings allowed",
        records.stream().map(Record::getType)
        .allMatch(s -> "true".equals(s) || "false".equals(s)));

With method reference it could be much nicer:

assertThat("only true & false strings allowed",
       records.stream().map(Record::getType).allMatch("true"::equals));

But can I anyhow add "false" to predicate?

Upvotes: 2

Views: 706

Answers (3)

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 280141

There is no method in the String class or in the JDK that I know of that is equivalent to your Predicate. You can make a custom one

public static boolean match(String arg) {
    return "true".equals(arg) || "false".equals(arg);
}

and use it

assertThat("only true & false strings allowed",
   records.stream().map(Record::getType).allMatch(Example::match);

Or you can use a Pattern regular expression as a Predicate

assertThat("only true & false strings allowed",
   records.stream().map(Record::getType)
          .allMatch(Pattern.compile("^(false|true)$").asPredicate()));

And, as suggested by Holger in comments, you could use

.allMatch(Arrays.asList("true", "false")::contains)

or something similar created from a Set.

Upvotes: 5

Sam Lindsay-Levine
Sam Lindsay-Levine

Reputation: 196

It's not a one-liner, but you could use the .or() method on Predicate:

Predicate<String> isTrue = "true"::equals;
Predicate<String> isFalse = "false"::equals;

assertThat("only true & false strings allowed",
   records.stream().map(Record::getType).allMatch(isTrue.or(isFalse)))

Upvotes: 0

dkatzel
dkatzel

Reputation: 31648

You can chain Predicates together using Predicate.and() and Predicate.or() but first you have to coerce your method reference to a predicate

Predicate<String> trueTest = "true"::equals;

you can then either do the chaining inside your match

records.stream().map(Record::getType).allMatch( trueTest.or("false"::equals));

or create a Predicate outside the stream

Predicate<String> trueTest = "true"::equals;
Predicate<String> trueOrFalseTest = trueTest.or("false"::equals);


records.stream().map(Record::getType).allMatch( trueOrFalseTest );

Eitherway, I don't find either one to be more legible than your original code.

Upvotes: 0

Related Questions