How to suitably compose Predicate and Function in a Java function? - java

The purpose is to create a new Predicate usable in a stream filter :
myCollectionOfElement
.stream()
.filter(
MyStaticHelperClass.compose(MyStaticHelperClass.getSubElement1OfTheElement(),MyStaticHelperClass.getPredicate1OnSubElement1()))
.sorted(MyStaticHelperClass.getOtherSubElement().reversed())
.limit(10)
.collect(Collectors.toList())
getSubElement1OfTheElement() returns Function<E,S> (E contains a S property)
getPredicate1OnSubElement1() returns Predicate<S>
I use static functions to expose method references and functions.
I do this because the stream is called in a Velocity template and this context doesn't support lambda syntax and method reference.
I don't want to create a static function for all possible combinaisons, so I really want them to be composable.
For example here, I don't want to have a static getPredicate1OnElementThatCheckProperty1OnTheSubElement1() because I can compose getSubElement1OfTheElement() and getPredicate1OnSubElement1().
So I need a compose function :
// returns a new Predicate constructed by applying Predicate predicate on the result of Function function
public static <E,S> Predicate<E> compose(Function<E,S> function, Predicate<S> predicate)
// most intuitive : lambda
return value -> predicate.test(function.apply(value));
// with method references
return function.andThen(predicate::test)::apply;
// predicate.compose is not available because Predicate interface doesn't extends Function interface
inspired by Is there a convenience method to create a Predicate that tests if a field equals a given value?
// step by step with variables
Function <S,Boolean> predicateFunction = predicate::test;
// a kind of #FunctionalInterface implicit "conversion" ? Predicate -> Function.
// is that safe ?
Function <E,Boolean> composed = function.andThen(predicateFunction::apply);
return composed::apply;
Edit :
It's called a cast context : https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html
// the implementation of my compose can also be this ugly one-liner :
return ((Function <S,Boolean>)predicate::test).compose(function)::apply;
So, we cannot implement a generic compose function taking any functional interface (in my case Function and Predicate) because the name of the abstract method differs for each interface (test and apply in my case).
I'm OK with that.
To conclude, what I really need is two static functions, one that converts a Predicate to a Function and the opposite. Every Predicate will be used as a Function and the final operation will convert the composed Function to Predicate in order to match with the parameter type of the filter function.
public static <S> Function<S,Boolean> predicateToFunction(Predicate<S> predicate){
return predicate::test;
}
public static <S> Predicate<S> functionToPredicate(Function<S,Boolean> function){
return function::apply;
}
Is that correct ?
If so, is there any interest in releasing the bounds in the function signature ?

I answer my own questions.
Use lambda :
value -> predicate.test(function.apply(value));
Or if you really want/have to write a compose function, signature must be something like :
public static <E,S> Predicate<E> compose(Function<E,S> function, Predicate<? super S> predicate)

I think the best approach would be use the boolean compose methods Predicate provides: and, or, not. e.g.,
private Predicate<String> startsWith(String prefix) {
return s -> s.startsWith(prefix);
}
private Predicate<String> endsWith(String suffix) {
return s -> s.endsWith(suffix);
}
Stream.of("Foo","Fuz","Doo","Fo")
.filter(startsWith("F").and(endsWith("o")))
.forEach(System.out::println);

Related

Difference between the signatures of Optional.map & Optional.flatMap methods [duplicate]

What's the difference between these two methods: Optional.flatMap() and Optional.map()?
An example would be appreciated.
Use map if the function returns the object you need or flatMap if the function returns an Optional. For example:
public static void main(String[] args) {
Optional<String> s = Optional.of("input");
System.out.println(s.map(Test::getOutput));
System.out.println(s.flatMap(Test::getOutputOpt));
}
static String getOutput(String input) {
return input == null ? null : "output for " + input;
}
static Optional<String> getOutputOpt(String input) {
return input == null ? Optional.empty() : Optional.of("output for " + input);
}
Both print statements print the same thing.
They both take a function from the type of the optional to something.
map() applies the function "as is" on the optional you have:
if (optional.isEmpty()) return Optional.empty();
else return Optional.of(f(optional.get()));
What happens if your function is a function from T -> Optional<U>?
Your result is now an Optional<Optional<U>>!
That's what flatMap() is about: if your function already returns an Optional, flatMap() is a bit smarter and doesn't double wrap it, returning Optional<U>.
It's the composition of two functional idioms: map and flatten.
Okay. You only need to use 'flatMap' when you're facing nested Optionals. Here's the example.
public class Person {
private Optional<Car> optionalCar;
public Optional<Car> getOptionalCar() {
return optionalCar;
}
}
public class Car {
private Optional<Insurance> optionalInsurance;
public Optional<Insurance> getOptionalInsurance() {
return optionalInsurance;
}
}
public class Insurance {
private String name;
public String getName() {
return name;
}
}
public class Test {
// map cannot deal with nested Optionals
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.map(Car::getOptionalInsurance) // ① leads to a Optional<Optional<Insurance>
.map(Insurance::getName); // ②
}
}
Like Stream, Optional#map will return a value wrapped by a Optional. That's why we get a nested Optional -- Optional<Optional<Insurance>. And at ②, we want to map it as an Insurance instance, that's how the tragedy happened.
The root is nested Optionals. If we can get the core value regardless the shells, we'll get it done. That's what flatMap does.
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.flatMap(Car::getOptionalInsurance)
.map(Insurance::getName);
}
In the end, I stronly recommed the Java 8 In Action to you if you'd like to study Java8 Systematicly.
Note:- below is the illustration of map and flatmap function, otherwise Optional is primarily designed to be used as a return type only.
As you already may know Optional is a kind of container which may or may not contain a single object, so it can be used wherever you anticipate a null value(You may never see NPE if use Optional properly). For example if you have a method which expects a person object which may be nullable you may want to write the method something like this:
void doSome(Optional<Person> person){
/*and here you want to retrieve some property phone out of person
you may write something like this:
*/
Optional<String> phone = person.map((p)->p.getPhone());
phone.ifPresent((ph)->dial(ph));
}
class Person{
private String phone;
//setter, getters
}
Here you have returned a String type which is automatically wrapped in an Optional type.
If person class looked like this, i.e. phone is also Optional
class Person{
private Optional<String> phone;
//setter,getter
}
In this case invoking map function will wrap the returned value in Optional and yield something like:
Optional<Optional<String>>
//And you may want Optional<String> instead, here comes flatMap
void doSome(Optional<Person> person){
Optional<String> phone = person.flatMap((p)->p.getPhone());
phone.ifPresent((ph)->dial(ph));
}
PS;
Never call get method (if you need to) on an Optional without checking it with isPresent() unless you can't live without NullPointerExceptions.
What helped me was a look at the source code of the two functions.
Map - wraps the result in an Optional.
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value)); //<--- wraps in an optional
}
}
flatMap - returns the 'raw' object
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value)); //<--- returns 'raw' object
}
}
Optional.map():
Takes every element and if the value exists, it is passed to the function:
Optional<T> optionalValue = ...;
Optional<Boolean> added = optionalValue.map(results::add);
Now added has one of three values: true or false wrapped into an Optional , if optionalValue was present, or an empty Optional otherwise.
If you don't need to process the result you can simply use ifPresent(), it doesn't have return value:
optionalValue.ifPresent(results::add);
Optional.flatMap():
Works similar to the same method of streams. Flattens out the stream of streams. With the difference that if the value is presented it is applied to function. Otherwise, an empty optional is returned.
You can use it for composing optional value functions calls.
Suppose we have methods:
public static Optional<Double> inverse(Double x) {
return x == 0 ? Optional.empty() : Optional.of(1 / x);
}
public static Optional<Double> squareRoot(Double x) {
return x < 0 ? Optional.empty() : Optional.of(Math.sqrt(x));
}
Then you can compute the square root of the inverse, like:
Optional<Double> result = inverse(-4.0).flatMap(MyMath::squareRoot);
or, if you prefer:
Optional<Double> result = Optional.of(-4.0)
.flatMap(MyMath::inverse)
.flatMap(MyMath::squareRoot);
If either the inverse() or the squareRoot() returns Optional.empty(), the result is empty.
You can refer below link to understand in detail (best explanation which I could find):
https://www.programmergirl.com/java-8-map-flatmap-difference/
Both map and flatMap - accept Function. The return type of map() is a single value whereas flatMap is returning stream of values
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
They do the same thing.
The only difference is that, the lambda return's type is wrapped by Optional or not.
For normal usage, map is shorter than flatMap
Example:
package bj;
import java.util.Optional;
import static java.lang.System.out;
public class App {
public static void main(String[] args) {
out.println(Optional.of(10).map (x -> x * x));
out.println(Optional.of(10).flatMap(x -> Optional.of(x * x)));
out.println(Optional.of(10).map (x -> Optional.of(x * x).get()));
out.println(Optional.<Integer>empty().map (x -> x * x));
out.println(Optional.<Integer>empty().flatMap(x -> Optional.of(x * x)));
out.println(Optional.<Integer>empty().map (x -> Optional.of(x * x).get()));
}
}
Output:
Optional[100]
Optional[100]
Optional[100]
Optional.empty
Optional.empty
Optional.empty

How should I design this method in order to take a list of lambda expressions as an input?

I have the following assignment:
Design a class whose objects have the methods:
setValue which, given a String and an integer value, associates the value with the noun of the variable
getValue which returns the integer value associated with a given String
execute which invokes in sequence a given list of lambda expressions, where each one takes an instance of the class, return nothing, and act on the class through the methods setValue and getValue.
So for the example, after the following:
MyClass instance = new MyClass();
instance.execute(List.of(e -> e.setValue("x", 1),
e -> e.setValue("y", 2)));
instance should contain the values 1 for "x" and 2 for "y".
Here is what I've done so far, I think it's alright:
public class MyClass {
private Map<String,Integer> map;
public int getValue(String name) {return map.get(name);}
public void setValue(String name, int value) {map.put(name, value);}
I am not seeing the way to go for execute. I know I need a functional interface for those lambda expressions, but then I can't solve errors shown by Eclipse when writing instance.execute(List.of(...)) , e.g. "The method of(Object, Object) in the type List is not applicable for the arguments ((<no type> e) -> {}, (<no type> e) -> {}).
How can I make it work?
You need to supply a list of Consumer<MyClass>. A Consumer is a functional interface with a single abstract method called accept which performs the action on the the given argument. Try this.
public void execute(List<Consumer<MyClass>> list) {
list.forEach(cons -> cons.accept(this));
}
The problem with List::of is that you have to either use Java 9 or you can simply do this.
public void execute(Consumer<MyClass> ...list) {
Stream.of(list).forEach(cons -> cons.accept(this));
}
You have it backwards: If you want to call the method for a number of values, those values are the stream. Presuming you have a Map<String, Integer> that represents your "x": 1 dataset, you can do this:
valuesMap.entrySet().stream()
.forEach(entry -> instance.setValue(entry.getKey(), entry.getValue());
Given your problem statement, though, it looks like you're being asked to do something closer to the Visitor pattern. In this case, you need an interface for the lambdas to implement, and there's a built-in one: Consumer<MyClass>. You should get familiar with this one as well as Supplier and Function, since they're very common.
If you declare your execute method to take a list of these, then you can use a for loop or a stream to process them, or use the convenient built-in forEach method:
public void execute(List<Consumer<MyClass>> consumers) {
consumers.forEach(consumer -> consumer.accept(this));
}

Optional ifPresent otherwise call another function

I wrote code that works, however I had to create extra lines, is there a way to compress that in one line? The logic: take last page, perform searching function by regex, if not located, take the page before and perform searching function by regex
Optional<String> totalBoxesLastPage = lastPage.locate(INVOICE_TOTAL_AMOUNT_BOXES);
Optional<String> totalBoxes = totalBoxesLastPage.isPresent() ?
totalBoxesLastPage : nextToLastPage
.flatMap(p -> p.locate(INVOICE_TOTAL_AMOUNT_BOXES));
Thank you guys
You may use orElseGet with a supplier to call some function which computes the value if the optional is empty. If a value is present, it returns the value, otherwise returns the result produced by the supplying function. In your case you have to pass Supplier<String>. Moreover, your return type after unwrapping the Optional should be a String, not an Optional<String>.
String totalBoxes = totalBoxesLastPage
.orElseGet(() -> nextToLastPage.flatMap(p -> p.locate(INVOICE_TOTAL_AMOUNT_BOXES))
.orElseThrow(IllegalStateException::new));
This worked out for me , i was really blind by not seeing .or function
or(Supplier<? extends Optional<? extends T>> supplier)
public Optional<String> findBetweenTwo(Page lastPage,Optional<Page> nextToLast,Pattern pattern) {
return lastPage.locate(pattern).or(() -> nextToLast.flatMap(p -> p.locate(pattern)));
}

Filter collection in Kotlin with existing java.util.Predicate instance

I want to filter a collection of values in Kotlin using an instance of a java.util.Predicate implementation, basically something like this:
val predicate = JsQueryPredicate<SportEvent>(query)
schedule.sport_events.filter(predicate)
This doesn't compile though. The following works, is that the recommended way of doing this? Feels a bit cumbersome
val predicate = JsQueryPredicate<SportEvent>(query)
schedule.sport_events.filter { predicate.test(it) }
You can use a method reference, which gets converted implicitly to a (T) -> Boolean and thus allows you to call the filter method:
schedule.sport_events.filter(predicate::test)
To answer it more directly: yes... predicate.test(it) or the nearly equivalent method reference predicate::test are the way to go... except...
If you have to deal with Java predicates more often and/or the refactoring of the Java functional types (e.g. Predicate) to Kotlin function types is planned in future, you may also want to add appropriate extension functions instead, e.g.:
fun <T> Iterable<T>.filter(predicate: Predicate<T>) = filter { predicate.test(it) }
With the following usage then:
val javaPredicate : Predicate<String> = Predicate { it == "hello" }
listOf("hello", "world")
.filter(javaPredicate)
If you replaced the Predicate in future to, e.g. (T) -> Boolean you then don't need to adapt that filter, but just replace/remove the import statement to the extension function.
Extension functions to just transform the Predicate to an appropriate Kotlin function type are possible too, but may not help you that much in future refactorings:
operator fun <T> Predicate<T>.invoke() : (T) -> Boolean = ::test
fun <T> Predicate<T>.transform() : (T) -> Boolean = ::test
Usage samples of those:
val javaPredicate : Predicate<String> = Predicate { it == "hello" }
// variant with Predicate.invoke:
listOf("hello", "world")
.filter(javaPredicate())
// variant using Predicate.transform()
listOf("hello", "world")
.filter(javaPredicate.transform())
So I recommend you the overloaded filter-method in case you plan a refactoring or otherwise just stick to filter { predicate.test(it) }/filter(predicate::test), which might make a future refactoring a bit (IDEs help ;-)) harder.

Call a method on the return value of a method reference

I have a stream of files that I want to filter based on the ending of the file name:
public Stream<File> getFiles(String ending) throws IOException {
return Files.walk(this.path)
.filter(Files::isRegularFile)
.map(Path::toFile)
.filter(file -> file.getName().endsWith(ending));
}
While the lambda in the last line is not bad, I thought I could use method references there as well, like so:
.filter(File::getName.endsWith(ending));
Or alternatively wrapped in parentheses. However, this fails with The target type of this expression must be a functional interface
Can you explain why this doesn't work?
Can you explain why this doesn't work?
Method references are syntactical sugar for a lambda expression. For example, the method reference File::getName is the same as (File f) -> f.getName().
Lambda expressions are "method literals" for defining the implementation of a functional interface, such as Function, Predicate, Supplier, etc.
For the compiler to know what interface you are implementing, the lambda or method reference must have a target type:
// either assigned to a variable with =
Function<File, String> f = File::getName;
// or assigned to a method parameter by passing as an argument
// (the parameter to 'map' is a Function)
...stream().map(File::getName)...
or (unusually) cast to something:
((Function<File, String>) File::getName)
Assignment context, method invocation context, and cast context can all provide target types for lambdas or method references. (In all 3 of the above cases, the target type is Function<File, String>.)
What the compiler is telling you is that your method reference does not have a target type, so it doesn't know what to do with it.
File::getName is a method reference and String::endsWith is as well. However they cannot be chained together. You could create another method to do this
public static Predicate<File> fileEndsWith(final String ending) {
return file -> file.getName().endsWith(ending);
}
and then use it
.filter(MyClass.fileEndsWith(ending))
This doesn't buy you much if you're not re-using it though.
A couple of helpers might assist in providing some semblance of what you wish for. Using the helpers below, you can replace your lambda with an expression containing method references, like this:
// since your predicate is on the result of a function call, use this to create a predicate on the result of a function
public static <A,B> Predicate<A> onResult(Function<A,B> extractor, Predicate<B> predicate){
return a -> predicate.test(extractor.apply(a));
}
// since your predicate involves an added parameter, use this to reduce the BiPredicate to a Predicate with one less parameter
public static <T,U> Predicate<T> withParam(BiPredicate<T,U> pred, U param){
return t -> pred.test(t,param);
}
public Stream<File> getFiles(String ending) throws IOException {
return Files.walk(Paths.get("."))
.filter(Files::isRegularFile)
.map(Path::toFile)
.filter(onResult(File::getName, withParam(String::endsWith, ending)));
}

Categories