Java 8 Feature Class addThen Default Method

I am learning Java-8 Lambda, I am trying to understand the default addThen method in the java.util.function.Function interface. As I understand it, addthen will first execute the first function and then execute the second method. Therefore, I created a program as shown below:

//Pojo class class Bike { public Bike(String bikeName, int price, String bikeType) { this.bikeName = bikeName; this.price = price; this.bikeType = bikeType; } private String bikeType; private String bikeName; private int price; public String getBikeType() { return bikeType; } @Override public String toString() { return "Bike [bikeType=" + bikeType + ", bikeName=" + bikeName + ", price=" + price + "]"; } public void setBikeType(String bikeType) { this.bikeType = bikeType; } public String getBikeName() { return bikeName; } public void setBikeName(String bikeName) { this.bikeName = bikeName; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } } //Main class public class FunctionInbuildDefaultMethodsExample { public static void main(String[] args) { learningAndThen(); } static void learningAndThen() { Function<Bike, String> updateBikefunction = (Bike bike) -> { System.out.println("OldBike Name is::" + bike.getBikeName()); bike.setBikeName("PULSOR-200CC"); return bike.getBikeName(); }; Function<Bike, String> updateBikePriceFunction = (Bike bike) -> { System.out.println("OldBike Price is::" + bike.getPrice()); bike.setPrice(95000); return bike.getBikeName(); }; /* * First update Bike and then price * */ /*Compilation error here*/ Function<Bike,String> bikeFunction = updateBikefunction.andThen(updateBikePriceFunction); bikeFunction.apply( new Bike("PULSOR-125CC", 65000, "BAJAJ")); } 

}

I get a compilation error in line

Function bikeFunction = updateBikefunction.andThen (updateBikePriceFunction);

as "The andThen (Function) method in the Function type is not applicable to (Function) arguments . " Having studied the source code of the functional interface, I understand that the addThen method is looking for an instance of type Function<String,Book> by default. My questions are: if the addThen method should execute the first function, and then the next fuction, which is passed as a parameter, why the default addThen method of the function method is written this way, except for an instance of type Function<String,Book> .

+5
source share
4 answers
 updateBikefunction = Bike -> String updateBikePriceFunction = Bike -> String updateBikefunction -> updateBikePriceFunction = Bike -> String -> Bike -> String ^^^^^^^^^^^^^^ 

To form a chain of functions, the previous result should be the output for the next function. This condition is violated.

updateBikefunction can be changed to Function<Bike, Bike>

  Function<Bike, Bike> updateBikefunction = (Bike bike) -> { ... return bike; }; 

to compile the line:

 Function<Bike, String> bikeFunction = updateBikefunction.andThen(updateBikePriceFunction); 
+3
source

The andThen Function method is used as a channel between functions.

Both Function are taken to Bike and return String , which is the problem.

When you call [function1].andThen[function2] , where both have the same parameterization <Bike, String> , [function2] expects Bike , but gets String from [function1] .

See docs (my bold):

Returns a folded function that first applies this function to its input, and then applies the after function to the result . If evaluating any of the functions throws an exception, it is passed to the caller of the linked function.

+3
source

andThen applies to the result of this Function . Thus, this will work, for example:

 Function<Bike, String> bikeFunction = updateBikefunction .andThen(s -> s.toUpperCase()); 

Since the result is a String from Function .

+3
source

Description

It is pretty simple. The function does not output tuples of type (Bike, String) ; it has Bike input and String output.

If you are now composing functions, the second function should use this output as its input , for example:

 Function1: A -> B Function2: B -> C Composed: A (-> B) -> C 

Your functions are

 updateBikefunction: Bike -> String updateBikePriceFunction: Bike -> String 

however, the compiler expects updateBikePriceFunction to use the output of updateBikefunction as its input, so it wants it to look like this:

 updateBikePriceFunction: String -> ... 

You can also see this in the documentation :

Interface Function<T,R>

andThen(Function<? super R,? extends V> after)

So, the object you are calling the method on has input T and outputs R Does the function you should use as an argument have an input ? super R ? super R and outputs ? extends V ? extends V


How to fix

If you want to bind manipulation methods, you should use Bike -> Bike and create your own method for final results like getBikeNameFunction , which then returns the name:

 Function<Bike, Bike> updateBikefunction = (Bike bike) -> { System.out.println("OldBike Name is::" + bike.getBikeName()); bike.setBikeName("PULSOR-200CC"); return bike; }; Function<Bike, Bike> updateBikePriceFunction = (Bike bike) -> { System.out.println("OldBike Price is::" + bike.getPrice()); bike.setPrice(95000); return bike; }; Function<Bike, String> getBikeNameFunction = (Bike bike) -> { return bike.getBikeName(); }; 

Now you can use it as follows:

 Function<Bike, String> bikeFunction = updateBikefunction .andThen(updateBikePriceFunction) .andThen(getBikeNameFunction); 

Or just use the method reference, for example:

 Function<Bike, String> bikeFunction = updateBikefunction .andThen(updateBikePriceFunction) .andThen(Bike::getName); 
+3
source

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


All Articles