Combining Predicates
A predicate can be composed of other predicates by means of the and()
and or()
methods as shown in the examples below.
and
The and()
method returns a composed predicate that represents a short-circuiting logical AND of a first predicate and another given second predicate. If the first predicate is evaluated to false
, then the second predicate is not evaluated.
The following code sample will print out all films that are long (apparently a film is long when its length is greater than 120 minutes) and that has a rating that is "PG-13":
Predicate<Film> isLong = Film$.length.greaterThan(120);
Predicate<Film> isPG13 = Film$.rating.equal("PG-13");
jpaStreamer.stream(Film.class)
.filter(isLong.and(isPG13))
.forEachOrdered(System.out::println);
This will produce the following output:
Film { filmId = 33, title = APOLLO TEEN, ... , length = 153, ..., rating = PG-13, ...
Film { filmId = 35, title = ARACHNOPHOBIA ROLLERCOASTER, ..., length = 147, ..., rating = PG-13, ...
Film { filmId = 36, title = ARGONAUTS TOWN, ..., length = 127, ..., rating = PG-13, ...
...
The same result can be achieved by just stacking two filter
operations on top of each other. So this:
jpaStreamer.stream(Film.class)
.filter(Film$.length.greaterThan(120))
.filter(Film$.rating.equal("PG-13"))
.forEachOrdered(System.out::println);
is equivalent to:
jpaStreamer.stream(Film.class)
.filter(Film$.length.greaterThan(120).and(Film$.rating.equal("PG-13"))
.forEachOrdered(System.out::println);
or
The or()
method returns a composed predicate that represents a short-circuiting logical OR of a first predicate and another given second predicate. If the first predicate is evaluated to true
, then the second predicate is not evaluated.
The following code sample will print out all films that are either long (length > 120) or has a rating of "PG-13":
Predicate<Film> isLong = Film$.length.greaterThan(120);
Predicate<Film> isPG13 = Film$.rating.equal("PG-13");
jpaStreamer.stream(Film.class)
.filter(isLong.or(isPG13))
.forEachOrdered(System.out::println);
This will produce the following output:
Film { filmId = 5, title = AFRICAN EGG, ..., length = 130, ..., rating = G, ...
Film { filmId = 6, title = AGENT TRUMAN, ..., length = 169, ..., rating = PG, ...
Film { filmId = 7, title = AIRPLANE SIERRA, ..., length = 62, ..., rating = PG-13, ...
...
As for the and()
method, there is an equivalent way of expressing compositions with or()
. Here is an example of how streams can be concatenated to obtain the same functionality as above:
StreamComposition.concatAndAutoClose(
jpaStreamer.stream(Film.class).filter(Film$.length.greaterThan(120)),
jpaStreamer.stream(Film.class).filter(Film$.rating.equal("PG-13"))
)
.distinct()
.forEachOrdered(System.out::println);
Film { filmId = 5, title = AFRICAN EGG, ..., length = 130, ..., rating = G, ...
Film { filmId = 6, title = AGENT TRUMAN, ..., length = 169, ..., rating = PG, ...
{... a number of films with length > 120}
Film { filmId = 7, title = AIRPLANE SIERRA, ..., length = 62, ..., rating = PG-13, ...
{... a number of films with rating = "PG-13}
...
In this case, optimized queries will be used for the two sub-streams but the films must be handled by the JVM from the .distinct()
operation.
JPAstreamer can optimize Predicate::or better than a concatenation of streams followed by a distinct() operation.
|