Java 8 lambda predicate chaining?

前端 未结 6 1685
渐次进展
渐次进展 2020-12-08 19:30

I can\'t get it to compile, is it even possible to chain predicate lambdas?

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


        
相关标签:
6条回答
  • 2020-12-08 19:48

    I was working on a similar problem of predicate chaining and came up with the following

    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);
    }
    

    The first parameter to chain is a lambda (Function) that returns a lambda (Predicate) so it needs a couple of arrows

    public static void yourExample() {
        String[] filterVals = { "1", "2" };
    
        Arrays.asList("1","2","3")
            .stream()
            .filter(chain(x-> (y-> y.equals(x)), filterVals))
            .count();
    }
    

    For comparison, here is what I was trying to achieve...

    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);
    }
    
    0 讨论(0)
  • 2020-12-08 19:52

    You can use:

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

    but it's not very elegant. If you're specifying the conditions in-line, just use one lambda:

    e -> e.equals("1") || e.equals("2")
    
    0 讨论(0)
  • 2020-12-08 19:54
    Arrays.asList("1","2","3").stream().filter( Arrays.asList("1", "2")::contains).count();
    

    and yes method "either" is good idea

        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;
        }
    

    or you can use import static java.util.function.Predicate.isEqual; and write isEqual("1").or(isEqual("2"))

    0 讨论(0)
  • 2020-12-08 19:57

    You can use with magic method $:

    <T> Predicate<T> $(Predicate<T> p) {
         return p;
    }
    
    Arrays.asList("1", "2", "3").stream().filter( $(e -> e=="1").or(e -> e=="2") ).count();
    
    0 讨论(0)
  • 2020-12-08 20:01
    Predicate<String> pred1 =  "1"::equals;
    Predicate<String> pred2 =  "2"::equals;
    
    public void tester(){
          Arrays.asList("1","2","3").stream().filter(pred1.or(pred2)).count();
    }
    

    You can move your separate your conditions to make it possible to recombine them other ways.

    0 讨论(0)
  • 2020-12-08 20:04

    This is just a small addition to @Chris Jester-Young answer. It is possible to make the expression shorter by using method reference:

    ((Predicate<String>) "1"::equals).or("2"::equals)
    
    0 讨论(0)
提交回复
热议问题