Java 8 can pass a method to a filter

I have many filters that call methods of a stream object and use String methods that take 1 parameter per 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 generate a filter so that it looks / works somehow like

.filter( compare(thisReturnsAString,contains(s) )
.filter( compare(thisReturnsAString2,endsWith(s) )
+4
source share
2 answers

There are several ways, but I agree with @shmosel. Improving readability will be small.

One possible solution:

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

A call to this method will look like this:

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

Where Pis the type of your object. A slightly adapted version, which, however, can lead to many 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 this method might look like this:

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

. , ; -)

EDIT: @shmosel Predicate vs Function

+4

filter , predicate, , .

compare() .

ComparatorPredicate.java:

- . ...

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

}

, , :

public class Data {
 String value;

 // getters and setters

}

- . , , PredicateCompartor, .

//  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());

;

+1

Source: https://habr.com/ru/post/1666895/


All Articles