2017-07-14 4 views
0

Beispiel: Filtern Sie eine Liste von Produkten, deren Preis auf fromPrice und toPrice basiert. Sie könnten entweder beide geliefert werden, oder nur einer.Java 8: Stream und Filter basierend auf optionalen Bedingungen

  1. aller Produkte, deren Preis größer als fromPrice
  2. aller Produkte, deren Preis weniger als toPrice
  3. aller Produkte, deren Preis zwischen fromPrice und toPrice

Produkt:

public class Product { 

    private String id; 

    private Optional<BigDecimal> price; 

    public Product(String id, BigDecimal price) { 
     this.id = id; 
     this.price = Optional.ofNullable(price); 
    } 
} 

PricePredicate:

public class PricePredicate { 

    public static Predicate<? super Product> isBetween(BigDecimal fromPrice, BigDecimal toPrice) { 
     if (fromPrice != null && toPrice != null) { 
      return product -> product.getPrice().isPresent() && product.getPrice().get().compareTo(fromPrice) >= 0 && 
        product.getPrice().get().compareTo(toPrice) <= 0; 
     } 
     if (fromPrice != null) { 
      return product -> product.getPrice().isPresent() && product.getPrice().get().compareTo(fromPrice) >= 0; 
     } 
     if (toPrice != null) { 
      return product -> product.getPrice().isPresent() && product.getPrice().get().compareTo(toPrice) <= 0; 
     } 
     return null; 
    } 
} 

Filter:

return this.products.stream().filter(PricePredicate.isBetween(fromPrice, null)).collect(Collectors.toList()); 

return this.products.stream().filter(PricePredicate.isBetween(null, toPrice)).collect(Collectors.toList()); 

return this.products.stream().filter(PricePredicate.isBetween(fromPrice, toPrice)).collect(Collectors.toList()); 

Gibt es eine Möglichkeit, mein Prädikat statt mit dem, wenn nicht null Kontrollen zu verbessern? Alles, was mit Optionals möglich ist?

Antwort

1

Nein, Optional ist nicht dazu gedacht, Null-Prüfungen zu ersetzen.

Aber Ihr Code kann durch die Vermeidung von Doppelarbeit verbessert werden, und durch die Vermeidung von null zurück, wenn beiden Argumente sind null (was für ein Prädikat eindeutig keine gültiger Wert ist):

public static Predicate<Product> isBetween(BigDecimal fromPrice, BigDecimal toPrice) { 
    Predicate<Product> result = product -> true; 

    if (fromPrice != null) { 
     result = result.and(product -> product.getPrice().isPresent() && product.getPrice().get().compareTo(fromPrice) >= 0); 
    } 

    if (toPrice != null) { 
     result = result.and(product -> product.getPrice().isPresent() && product.getPrice().get().compareTo(toPrice) <= 0); 
    } 

    return result; 
} 
+1

Der erste Satz ist genug, um ein +1 von mir zu verdienen. – Jubobs

+0

Danke. Das sieht gut aus. aber ich bekomme einen Kompilierfehler hier: Optional price = product.getPrice(); kann Symbol "Produkt" nicht auflösen –

+0

Oh ja, sorry, mein Code macht keinen Sinn. Lass es mich reparieren. –

0

Sie verwenden Apache Commons Lang, bietet es null sicheren Vergleich:

ObjectUtils.compare(from, to) 

null is assumed to be less than a non-value