Search code examples
javalambdafunctional-programmingpredicatehigher-order-functions

Using a predicate for a query on a field


I'm messing around with lambdas and I'm trying to create a generic way to form a predicate for a class on a field. Here's some code to illustrate:

public class A {

private String b;
private String c;

public A(String b, String c) {
    this.b = b;
    this.c = c;
}

public String getB() {
    return b;
}

public String getC() {
    return c;
}

}

public class Main {

public static void main(String[] args) {
    List<A> list = Arrays.asList(new A("aa","bb"),new A("aaC","bb"));
    Test test = new Test();
    test.setList(list);
    test.createPred("aa");
}

}


public class Test {

private List<A> list;

public void setList(List<A> list) {
    this.list = list;
}

public Predicate<A> createPred(String query) {
    return new Predicate<A>() {
        @Override
        public boolean test(A t) {
            return t.getB().equals(query);
        }
    };
}

public List<A> search(Predicate<A> a) {
    return list.stream().filter(a).collect(Collectors.toList());
}
}

How can I write createPred so it can take a field? I want the method to be "field-generic" I suppose. I'm guessing using java reflection here is not a good idea.


Solution

  • You can make your method take a Function and a T as the query field.

      public static void main(String[] args) {
        List<A> list = Arrays.asList(new A("aa", "bb"), new A("aaC", "bb"));
        Test test = new Test();
        test.setList(list);
        test.createPred("aa", A::getB);
      }
    
    
    
      public static class Test {
    
        private List<A> list;
    
        public void setList(List<A> list) {
          this.list = list;
        }
    
        public <T> Predicate<A> createPred(T query, Function<A, T> f) {
          return new Predicate<A>() {
            @Override
            public boolean test(A x) {
              return f.apply(x).equals(query);
            }
          };
        }
    
        public List<A> search(Predicate<A> a) {
          return list.stream().filter(a).collect(Collectors.toList());
        }
      }