Je n'arrive pas à le compiler, est-il même possible d'enchaîner les lambdas des prédicats?
Arrays.asList("1","2","3").stream().filter( (e -> e=="1" ).or(e-> e=="2") ).count();
Ou le seul moyen est de créer explicitement un prédicat puis de combiner comme suit:
Predicate<String> isOne= e -> e=="1";
Arrays.asList("1","2","3").stream().filter( isOne.or(e -> e=="2") ).count();
Ou existe-t-il un moyen plus "fonctionnel et élégant" de réaliser la même chose?
Vous pouvez utiliser:
((Predicate<String>) e -> e.equals("1")).or(e -> e.equals("2"))
mais ce n'est pas très élégant. Si vous spécifiez les conditions en ligne, utilisez simplement un lambda:
e -> e.equals("1") || e.equals("2")
Je travaillais sur un problème similaire de chaînage de prédicats et suis arrivé avec le suivant
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);
}
Le premier paramètre à chaîner est un lambda (Fonction) qui renvoie un lambda (prédicat), il faut donc deux flèches.
public static void yourExample() {
String[] filterVals = { "1", "2" };
Arrays.asList("1","2","3")
.stream()
.filter(chain(x-> (y-> y.equals(x)), filterVals))
.count();
}
A titre de comparaison, voici ce que j'essayais de réaliser ...
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);
}
Vous pouvez utiliser avec la méthode magique $:
<T> Predicate<T> $(Predicate<T> p) {
return p;
}
Arrays.asList("1", "2", "3").stream().filter( $(e -> e=="1").or(e -> e=="2") ).count();
Ceci est juste un petit ajout à la réponse de @Chris Jester-Young. Il est possible de raccourcir l'expression en utilisant la référence de la méthode:
((Predicate<String>) "1"::equals).or("2"::equals)
Arrays.asList("1","2","3").stream().filter( Arrays.asList("1", "2")::contains).count();
et oui méthode "soit" est une bonne idée
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;
}
ou vous pouvez utiliser import static Java.util.function.Predicate.isEqual;
.__ et écrire isEqual("1").or(isEqual("2"))
Predicate<String> pred1 = "1"::equals;
Predicate<String> pred2 = "2"::equals;
public void tester(){
Arrays.asList("1","2","3").stream().filter(pred1.or(pred2)).count();
}
Vous pouvez déplacer votre séparer vos conditions pour permettre de les recombiner autrement.