Composing predicates

Let's assume that we have the following Melon class and List of Melon:

public class Melon {

private final String type;
private final int weight;

// constructors, getters, setters, equals(),
// hashCode(), toString() omitted for brevity
}

List<Melon> melons = Arrays.asList(new Melon("Gac", 2000),
new Melon("Horned", 1600), new Melon("Apollo", 3000),
new Melon("Gac", 3000), new Melon("Hemi", 1600));

The Predicate interface comes with three methods that take a Predicate and uses it to obtain an enriched Predicate. These methods are and(), or(), and negate().

For example, let's assume that we want to filter the melons that are heavier than 2,000 g. For this, we can write a Predicate, as follows:

Predicate<Melon> p2000 = m -> m.getWeight() > 2000;

Now, let's assume that we want to enrich this Predicate to filter only melons that respect p2000 and are of the Gac or Apollo type. For this, we can use the and() and or() methods, as follows:

Predicate<Melon> p2000GacApollo 
= p2000.and(m -> m.getType().equals("Gac"))
.or(m -> m.getType().equals("Apollo"));

This is interpreted from left to rights as a && (b || c), where we have the following:

  • a is m -> m.getWeight() > 2000
  • b is m -> m.getType().equals("Gac")
  • c is m -> m.getType().equals("Apollo")

Obviously, we can add more criteria in the same manner.

Let's pass this Predicate to filter():

// Apollo(3000g), Gac(3000g)
List<Melon> result = melons.stream()
.filter(p2000GacApollo)
.collect(Collectors.toList());

Now, let's assume that our problem requires that we obtain the negation of the aforementioned compound predicate. It is cumbersome to rewrite this predicate as !a && !b && !c or any other counterpart expression. A better solution is to call the negate() method, as follows:

Predicate<Melon> restOf = p2000GacApollo.negate();

Let's pass it to filter():

// Gac(2000g), Horned(1600g), Hemi(1600g)
List<Melon> result = melons.stream()
.filter(restOf)
.collect(Collectors.toList());

Starting with JDK 11, we can negate a Predicate that's passed as an argument to the not() method. For example, let's filter all the melons that are lighter than (or equal to) 2,000 g using not():

Predicate<Melon> pNot2000 = Predicate.not(m -> m.getWeight() > 2000);

// Gac(2000g), Horned(1600g), Hemi(1600g)
List<Melon> result = melons.stream()
.filter(pNot2000)
.collect(Collectors.toList());
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.31.163