Question: i have many filters calling methods of the streamed object and using String methods that take 1 parameter on the result:

```
String s = "aComarisonString";

stream().filter( p -> p.thisReturnsAString().startsWith(s) )
stream().filter( p -> p.thisReturnsAString2().startsWith(s) )
stream().filter( p -> p.thisReturnsAString().endsWith(s) )
stream().filter( p -> p.thisReturnsAString().contains(s) )

```

is there a way to generify the filter so it looks/works something like

```
.filter( compare(thisReturnsAString,contains(s) )
.filter( compare(thisReturnsAString2,endsWith(s) )

```

Answer: 
There are several ways, but I agree with @shmosel. There will be only little to no improvement in readability.

One of the possible solutions:

```
<V, P> Predicate<? super P> compare(Function<P, V> valueFunction, Predicate<V> matchPredicate) {
  return p -> matchPredicate.test(valueFunction.apply(p));
}

```

A call to that method would look like:

```
stream().filter(compare(P::thisReturnsAString, s -> s.endsWith(comparisonString)))

```

Where `P` is the type of your object. A slightly adapted variant, which might however lead to lots of overloaded methods:

```
<V, C, P> Predicate<? super P> compare(Function<P, V> valueFunction, BiPredicate<V, C> matchPredicate, C value) {
  return p -> matchPredicate.test(valueFunction.apply(p), value);
}

```

A call to that method could look like this:

```
stream().filter(compare(P::thisReturnsAString, String::endsWith, comparisonString))

```

No real gain here. Just an other way to write, what you wrote with more boilerplate code ;-)

EDIT: added the suggestion from @shmosel regarding Predicate vs Function
`filter` function is an intermediary operation and it require `predicate` to apply to each element to determine if it should be included in the new stream.

You need to create another utility method `compare()` in your utility class. 

**ComparatorPredicate.java :**

You can define the business rules to compare two strings in helper methods. An example ...

```
public class ComparatorPredicate {
public static String criteria = "aComarisonString";

public static Predicate<Data> startWith(){
    return p -> p.getValue().startsWith(criteria);
}

public static Predicate<Data> endsWith(){
    return p -> p.getValue().endsWith(criteria);
}

public static Predicate<Data> contains(){
    return p -> p.getValue().contains(criteria);
}

}

```

Assuming, you have list of data strings, then you can do the following;

```
public class Data {
 String value;

 // getters and setters

}

```

Then you do not need to add lambda expression in each statement. All you need to call comparator methods in PredicateCompartor class, which make your code clean and less repetitive. 

```
//  data list
List<Data> dataList = new ArrayList<>();

// list of strings start with 
List<Data> list1 = stringList.stream().filter(startWith()).collect(Collectors.toList());

// list of strings ends with
List<Data> list2 = stringList.stream().filter(endsWith()).collect(Collectors.toList());

// list of strings contains
List<Data> list3 = stringList.stream().filter(contains()).collect(Collectors.toList());

```

Note; these are just examples for demonstration