2015-10-02 2 views
3

Учитывая следующие функции:Vararg предикаты с Java 8 потока

public static <X> List<X> filterWithVarargPredicates(
     List<X> allProducts, 
     Predicate<X>... predicates 
    ) { 
     for (Predicate<X> predicate : predicates) { 
      allProducts = allProducts.stream() 
       .filter(predicate) 
       .collect(toList()); 
     } 

     return allProducts; 
    } 

Есть ли способ, чтобы потреблять все предикаты, не перебрать их и повторно назначить в списке? Например, было бы здорово, если бы у .stream() был фильтр, который использовал varargs, или каким-то образом сделать это в пределах одного потока.

ответ

0

Он делает. Потоки - это обычные объекты - вы можете хранить их в переменных и т. Д.

Stream<X> stream = allProducts.stream(); 
    for (Predicate<X> predicate : predicates) { 
     stream = stream.filter(predicate); 
    } 

    return stream.collect(toList()); 
+1

Использование гипотетических 'операции потока foldLeft', который был бы кратчайшее решение:' Stream.of (предикаты) .foldLeft (allProducts.stream(), поток: : фильтр) .collect (ToList()) '. К сожалению, нет 'foldLeft' еще ... –

+0

@TagirValeev Вложенные потоки - верный способ запутать людей, я уверен. – immibis

3

Я могу предложить создать один новый предикат, который объединить все остальные:

Predicate<X> allPredicates = x -> Arrays.stream(predicates) 
      .mapToInt(predicate -> !predicate.test(x)? 1: 0).sum()==0; 
allProducts = allProducts.stream().filter(allPredicates).collect(toList()); 

EDIT Лучший способ от @Holger ответа How to apply multiple predicates to a java.util.Stream?

Predicate<X> allPredicates = Arrays.stream(predicates) 
            .reduce(Predicate::and) 
            .orElse(x->true); 
1

Я бы написать метод для объединения многих предикатов в один.

@SafeVarargs 
static <T> Predicate<T> allTrue(Predicate<? super T>... predicates) { 
    return t -> { 
     for (Predicate<? super T> predicate : predicates) 
      if (!predicate.test(t)) 
       return false; 
     return true; 
    }; 
} 

Тогда вы можете сделать:

allProducts.stream() 
      .filter(allTrue(predicates)) 
      .collect(Collectors.toList()); 
+0

Это хорошее решение, если у вас больше предикатов. – Holger

Смежные вопросы