Подтвердить что ты не робот

Java 8 лямбда-предикат?

Я не могу его скомпилировать, возможно ли даже цепочку предикатов lambdas?

Arrays.asList("1","2","3").stream().filter( (e -> e=="1" ).or(e-> e=="2") ).count();

Или единственный способ - явно создать предикат, а затем объединить его так:

Predicate<String> isOne= e -> e=="1";
Arrays.asList("1","2","3").stream().filter( isOne.or(e -> e=="2") ).count();

Или существует ли более "функционально элегантный" способ достичь того же?

4b9b3361

Ответ 1

Вы можете использовать:

((Predicate<String>) e -> e.equals("1")).or(e -> e.equals("2"))

но это не очень элегантно. Если вы задаете условия в строке, просто используйте один лямбда:

e -> e.equals("1") || e.equals("2")

Ответ 2

Я работал над аналогичной проблемой цепочек предикатов и придумал следующий

public static <T> Predicate<T> chain (Function<T,Predicate<T>> mapFn, T[]args) {
    return Arrays.asList(args)
        .stream()
        .map(x->mapFn.apply(x))
        .reduce(p->false, Predicate::or);
}

Первым параметром для цепочки является лямбда (функция), которая возвращает лямбда (Predicate), поэтому ему нужно несколько стрелок

public static void yourExample() {
    String[] filterVals = { "1", "2" };

    Arrays.asList("1","2","3")
        .stream()
        .filter(chain(x-> (y-> y.equals(x)), filterVals))
        .count();
}

Для сравнения, вот что я пытался достичь...

public static void myExample() {
    String[] suffixes = { ".png", ".bmp" };
    Predicate<String> p = chain (x-> y-> y.endsWith(x), suffixes);
    File[] graphics = new File("D:/TEMP").listFiles((dir,name)->p.test(name));
    Arrays.asList(graphics).forEach(System.out::println);
}

Ответ 3

Вы можете использовать с магическим методом $:

<T> Predicate<T> $(Predicate<T> p) {
     return p;
}

Arrays.asList("1", "2", "3").stream().filter( $(e -> e=="1").or(e -> e=="2") ).count();

Ответ 4

Это просто небольшое дополнение к ответу @Chris Jester-Young. Можно сделать выражение короче, используя ссылку на метод:

((Predicate<String>) "1"::equals).or("2"::equals)

Ответ 5

Arrays.asList("1","2","3").stream().filter( Arrays.asList("1", "2")::contains).count();

и да метод "либо" - хорошая идея

    public static void main(String[] args) {
        long count = Arrays.asList("1","2","3").stream().filter(either("1"::equals).or("2"::equals)).count();
        System.out.println(count);
    }

    private static <T> Predicate<T> either(Predicate<T> predicate) {
        return predicate;
    }

или вы можете использовать import static java.util.function.Predicate.isEqual; и напишите isEqual("1").or(isEqual("2"))