Method reference and Lambda expression - java

I´m currently reading through someone else´s code and he has the following two methods:
public static double fac(double d) {
return d <= 0 ? 1 : d * fac(d - 1);
}
public static DoubleUnaryOperator getfun() {
return LamdaTests::fac; // LamdaTests is the classname of this class
}
First of all, i´m currently trying to understand lambda expressions/method references.
I have 2 questions:
1) What does the getFun() method exactly do? It should call the fac(double d) method in this class LambdaTests right? But with which argument and how can the return value be a DoubleUnaryOperator, shouldn´t "LamdaTests:fac" return a double?
2) What would be the equivalent Lamda expression for Lamdatests::fac in this case?
Edit: As far as i know
return LamdaTests::fac;
should be equal to
return x -> fac(x);
But i just dont understand where it gets the argument x from.

getFun doesn't call anything. It just returns a reference to the fac function. You need to call the returned function still to get a result. getFac isn't very useful here, so that may be what's confusing things. In reality, you would just use LamdaTests::fac directly, unless that method was private.
For the latter question, think of it this way:
x -> fac(x)
is a function that takes a double and returns a double. What is fac? It's the same thing: a function that takes a double and returns a double. The argument is just implicit here.

Related

How do you use a lambda expresion with complex math in java [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
hello i a trying to compare to values after i apply a lambda experrsion to them im trying to compare a location of a player and another to see the distance between them and im having trouble with lambdas
public class mathprob {
public static void main(String[] args) {
}
Location loc = player.getlocation();
Location newloc = player.getlocation();
(loc, newloc) -> Math.pow((loc.getX()-newloc.getX()), 2) +
Math.pow(loc.getY()-newloc.getY(), 2)+Math.pow(loc.getZ()-
newloc.getZ(),
2));
}
i keep getting a error because the lambda is incorrect i dont know how to use a lambda in this situation and then comparing the two values to each other (loc, newloc) the two values or two points P1(loc.getX(), loc,getY(), loc.getZ()) and P2(newloc.getX(), newloc.getY(), newloc.getZ()) i wanna compare the x and the y and the z of each point to see the number gap between them
Lambdas are just a way to create a type for a function. Keep in mind that a function has no "values" and hasn't been executed yet.
You can apply any Lambda to a set of values by calling it's apply method. It will then take the inputs (parameters to apply) and return the value as the result. A Lambda for a function that looks like this
(Coordinate x) -> { return new Distance(Math.sqrt(x.x * x.x + x.y * x.y)) }
would return the distance to the origin for a Coordinate assuming a Coordinate looked a little like
public class Coordinate {
public double x;
public double y;
}
and Distance looked a bit like like
public class Distance {
public Distance(double value) {
... whatever the implementation is ...
}
}
This function has a type conversion in it, it takes a Coordinate and returns a Distance. This means it fits the java "interface" of
Function<Coordinate, Distance>
and just by writing this Lambda
(Coordinate x) -> { return new Distance(Math.sqrt(x.x * x.x + x.y * x.y)) }
The Java compiler will generate some unnamed class of type Function<Coordinate, Distance> and instantiate an instance (create an object the class) to use in the context of the location of the Lambda.
Now if that lambda is within a method of a stream, such that the stream's parameter types are compatible, the stream will (in some manner) call apply on each value the stream is handling. Those values come from a Supplier which is basically an object that has a T get() method.
Stream calls the Supplier's get() method.
Stream has a method .forEach( ... ) containing a lambda that consumes the get() type.
Stream applies the value of get() to the lambda in forEach() by passing it into apply(value).
Stream collects the result of apply(value)
Stream returns from the .forEach(...) method a new stream with values typed to match the return value of the lambda in the forEach() method.
Eventually, these values are passed into a Collector method which combines values into some sort of buffer. Sometimes a List, sometimes a single value.
Conveniences exist for various ways of simplifying the collectors. Conveniences exist for generating values without coding suppliers.
The lambda syntax itself is a convenience for not having to write an implementation of one of the "xxxFunction" interfaces, create an object of it, and pass it into the stream.
Predicates are what they call Functions that return boolean values. There are even more convenience functions that work with predicates.
So, if you don't have a collection of data points to process, you probably shouldn't be using lambdas. If you do have a collection of data points to process, then keep in mind that streams and lambdas provide a new not-quite-like-a-loop way of processing them. They are guaranteed to be applied to all values, but the order of their application is not necessarily in the strong ordering that a traditional loop would apply. With the right options, you can effectively split the input into multiple chunks (spliterator vs iterator) and process the data in parallel.
Now that you have a quick overview of Lambdas, Streams, and the Functional interfaces, you can see that
(loc, newloc) -> Math.pow((loc.getX()-newloc.getX()), 2) +
Math.pow(loc.getY()-newloc.getY(), 2)+Math.pow(loc.getZ()-newloc.getZ(),
2));
wouldn't "do" anything, because at best it describes this
public class MyFunction implements Function<Location, Location, Double> {
Double apply(Location first, Location second) {
return Math.pow((first.getX()-second.getX()), 2)
+ Math.pow(first.getY()-second.getY(), 2)
+ Math.pow(first.getZ()-second.getZ(), 2)
}
}
MyFunction myFunc = new MyFunction();
Which has the following problem"
It's a coding error as it's only creating the facility to transform locations, and never using it.
Using the facility would look like
double result = myFunc.apply(loc, newloc);
Now, the very astute readers will mention auto-boxing, but in reality the compiler would choose the ToDoubleBiFunction type, probably side-stepping some of the possible auto-boxing issues. I just didn't want to write the example up in the non-generic manner, as again, the primitive functional types are a convenience (and optimization) of the general "all object" description above.
Lambda expressions are used to generate anonymous functions. They can be used where a #FunctionalInterface is expected.
Read more about them here: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
If you'd like your code to work you can assign your lambda to a BiFunction variable and then execute it passing in the loc and newloc.
public class mathprob {
public static void main(String[] args) {
Location _loc = player.getlocation();
Location _newloc = player.getlocation();
BiFunction<Location, Location, Double> lambdaExpression = (loc, newloc) -> {
return Math.pow((loc.getX()-newloc.getX()), 2) +
Math.pow(loc.getY()-newloc.getY(), 2)+Math.pow(loc.getZ()-newloc.getZ(),
2);
};
double result = lambdaExpression.apply(_loc, _newloc);
}
}
Here is an example of how the equivalent method declaration would look like instead of using a lambda:
public class mathprob {
public static void main(String[] args) {
Location loc = player.getlocation();
Location newloc = player.getlocation();
double result = calculate(loc, newloc);
}
public static double calculate(Location loc, Location newloc) {
return
Math.pow((loc.getX() - newloc.getX()), 2) +
Math.pow(loc.getY() - newloc.getY(), 2) +
Math.pow(loc.getZ() - newloc.getZ(), 2);
}
}
Read the 14.5. Statements from JLS.
value;
is not a valid statement, as
"text"; or 5; are not.
Lambda Expression is a value, which constitutes an anonymous method, and which can be assigned to the variable (of Functional Interface type) or can be passed into method, as an ordinary argument value.
public void someMethod() {
5; //does not compile, as this is not a statement.
int x = 5; //compiles, as this is a statement.
//Similarly,
() -> System.out.println("Hi"); //does not compile, as this is not a statement
Runnable r1 = () -> System.out.println("Hi"); //compiles, as this is a statement
}

Return statement in Helper Method(Java)

I am practicing simple coding problems from codingbat. One of the problems are asking me to use helper method to prevent redundant codes. However, I am very lost because I do not know why I should use public and int as return type for this problem.(because the question asks me to use header below)
public int fixTeen(int n)
What does the return from the helper method doing? Also, how do I know if I should use private or public for my helper method?
Please take a look at my code.
// Given 3 int values, a b c, return their sum. However, if any of the values
// is a teen -- in the range 13..19 inclusive -- then that value counts as 0,
// except 15 and 16 do not count as a teens. Write a separate helper
// "public int fixTeen(int n) {"that takes in an int value and returns that value
// fixed for the teen rule. In this way, you avoid repeating the teen code 3
// times (i.e. "decomposition"). Define the helper below and at the same
// indent level as the main noTeenSum().
public int noTeenSum(int a, int b, int c) {
return fixTeen(a) + fixTeen(b) + fixTeen(c);
}
public int fixTeen(int n) {
if (n >= 13 && n <= 19 && n != 15 && n != 16)
n = 0;
return n;
}
Edit:
What is the difference between setting return type void and int for the helper method? At first, I thought return int is unnecessary and tried to set the return type as void but it gave me an error.
In general, at least for the beginnings of java, methods should be named public. Later on, when you get to object oriented programming, the area it's in (public or private) matters more. For example, adding the keyword "public" means that that value can be accessed outside of the class, while "private" means it cannot. This is important for when you don't want the end user to be able to access your private data.
Point is, when you make a method, for now have them set to public.
Next up is the helper method. After the "public" or "private", you have the return type. You have it set to "int". Therefore, the return type must be an integer. It can't be a string, or a double - it must be an integer. If you set the return value to "void", then there would be no return value, and if you tried to write "return(n);", it would give you an error.
So TLDR: It's named "public" because you want to be able to access this method outside of the class, and it says "int", because you need to return an integer type. Then, when you return(n), it'll give the value, say, a == 7, and if b == 18, it'll set b == 0. After that, it adds the numbers together, and you have your answer!

Unable to understand lambdas AND longstream methods

I have such code example.
import java.util.LinkedList;
import java.util.List;
import java.util.stream.LongStream;
public class RemovedNumbers {
public static List<long[]> removNb(long n) {
System.out.println(n);
long sum = ((n + 1) * n / 2);
long minMultiplication = sum - 2 * n + 1;
long minCandidate = (long) Math.sqrt(minMultiplication);
LinkedList<long[]> list = new LinkedList<>();
LongStream.rangeClosed(minCandidate, n)
.mapToObj(a -> new long[]{a, calculateB(a, sum)})
.filter(longs -> longs[0] > longs[1])
.filter(longs -> longs[1] <= n)
.filter(longs -> longs[0] * longs[1] == sum - longs[0] - longs[1])
.forEach(longs -> addArrays(list, longs));
return list;
}
private static long calculateB(long a, long sum) {
return (sum - a) / (a + 1);
}
private static void addArrays(final LinkedList<long[]> list, final long[] longs) {
list.addFirst(new long[]{longs[1], longs[0]});
list.add(longs);
}
}
This code is complicated for me in LongStream part.
I don't get some points, so I need a help:
I examine LongStream class.
This class uses four methods: rangeClosed, mapToObj, filter, forEach (their description I found on Java docs). Unfortunately, now I am starting to examine java 1.8 version, so I can't understand how it works and what's happens.
Where is appeared "a" in mapToObj? What is it? I don't see var "a" declaration in previous part of code.
As I've got lambda is made by such scheme: (arguments) -> (body). So the "a" is an argument, "new long[]..." - is a body. This part isn't causes any question for me. But the next one, whereis "longs" - argument, "longs[0] > longs[1]" - body, causes some questions. What is the var "longs"? It hasn't declaration in the past! HOW it appears? How it works?
Am I right that LongStream class can be writes in one line? Like: LongStream.rangeClosed().filter().filter().filter().forEach(); ?
Am I right that all methods execute consequently? By each other? The first rangeClosed, then mapToObj, then filter... or is there another order?
Thanks a lot!
Your third point kind of answers your second point - a is the parameter of the lambda expression passed to mapToObj.
If you can understand that, then your fourth point should be easy to understand as well. longs is the parameter for the lambda expression passed to filter. Remember that you can name your parameter names whatever you like. I guess the reason why the author of the code renamed the parameter to longs is because in the previous line, each long in the stream is mapped into a long[], so now it's a stream of long arrays.
Am I right that LongStream class can be writes in one line?
Yes, but you would end up with a super long line of code, so we almost never do that.
Am I right that all methods execute consequently? By each other? The first rangeClosed, then mapToObj, then filter... or is there another order?
The methods get called in that order, but the operations they do won't run immediately. This is the cool part of streams. The longs will only be mapToObj'ed and filter'ed when you do forEach, a terminal operation. In other words, mapToObj and filter are kind of like saying "this is what this stream should do..." and when you do forEach, you are saying "now do it!"
If you still don't get what streams are doing, try to think of them as a production line in a factory. At the start, you have longs on the conveyer belts. And then they pass through a machine, transforming each of them into a long[]. After that, they pass through three filters. These filters will push them off the conveyer belt unless the long arrays fulfil some condition.
EDIT:
If you want to write this code without lambdas, you can write it with anonymous classes instead:
LongStream.rangeClosed(minCandidate, n)
.mapToObj(new LongFunction<long[]>() {
#Override
public long[] apply(long a) {
return new long[]{a, calculateB(a, sum)};
}
})
.filter(new Predicate<long[]>() {
#Override
public boolean test(long[] longs) {
return longs[0] > longs[1] &&
longs[1] <= n &&
longs[0] * longs[1] == sum - longs[0] - longs[1];
}
})
.forEach(new Consumer<long[]>() {
#Override
public void accept(long[] longs) {
addArrays(list, longs);
}
});
Each lambda expression implements a functional interface, or to be more specific, it implements the single abstract method of that functional interface.
Therefore, in a -> new long[]{a, calculateB(a, sum)}, a is the argument of the method implemented by the functional interface. Since mapToObj accepts an argument of type LongFunction, this lambda expression implements the R apply(long value) method of that interface, which means that lambda expression can also be written as (long a) -> new long[]{a, calculateB(a, sum)}.
This mapToObj call transforms the LongStream to a Stream<long[]>, so the lambda expression of the following filter call - longs -> longs[0] > longs[1] can also be written as (long[] longs) -> longs[0] > longs[1] - it implements the functional interface Predicate<long[]>, which means it implements boolean test(long[] t).
Yes, you can write this entire stream pipeline in a single line, but it would be more readable split into multiple lines.
Am I right that all methods execute consequently? By each other? The first rangeClosed, then mapToObj, then filter... or is there another order
Not exactly. While each intermediate method produces an output used as input to the next method, the evaluation of these methods only begins once the terminal operation - forEach in this case - is executed. And these operations don't necessarily process all the elements of the Stream. For example, if the terminal operation would be firstFirst() instead of forEach, the pipeline would only process enough elements until the first element that passes all the filters is found.
Am I right that LongStream class can be writes in one line?
What you're witnessing here is method chaining. This is where method after method can get chained to eachother. This can be done for almost all classes.
Everything else is pretty much answered by Sweeper.
3 and 4:
you are tryng to understand how lambda work so I'll break it down your code for you:
// this return a LongStream obj
LongStream.rangeClosed(minCandidate, n)
// so with point notation you can access to one of the method in LongStream
// matToObj in this case.
.mapToObj(a -> new long[]{a, calculateB(a, sum)})
what is a? What ->? what the other stuff?
MapToObj takes a IntFunction mapper argument and a is a declaration of that type on the fly this is why you didin't see it before in the code.
the arrow indicates that the right site is the lamba expression, if you have a inline operation you can omit the return statement and you can not include {} brackets so imagine that statement like a return statement.
With lamba functions you can easily create chains of operation this is why you have many functions called one after another. You have to keep in mind that the next function takes as argument an object type that is of the same type of the return type of the previous function.

Confusing behaviour of overloading

I am experiencing a behaviour that I do not understand related to this code snippet. More precisely, I was expecting the call of getUniqueCost method for the case in which the operator is of type Projection (that is, when n.isProjection() is true) to be calling the method having as signature private double getUniqueCost(final Projection p) instead of that having signature private double getUniqueCost(final Node p).
Note that Projection is a subclass of Node.
Here the code for the two aforementioned methods:
private double getUniqueCost(final Node n){
if(n.isScan())
return getUniqueCost(estimateCardinality(n));
if(n.isJoin())
return getUniqueCost((NJoin) n);
if(n.isUnion())
return getUniqueCost((Union) n);
if(n.isMaterialization())
return getUniqueCost(n.getChildren().iterator().next());
if(n.isProjection()){
return getUniqueCost(child.isJoin() ?
n.getChildren().iterator().next() : ((Projection) n));
}
throw new IllegalArgumentException("Unknown node type: " + n.getOperator());
}
private double getUniqueCost(final Projection p){
return getUniqueCost(estimateCardinality(p)) +
getUniqueCost(p.getChildren().iterator().next());
}
The only way to actually manage to call the second method was to modify the first method as follows (the omitted code is the same as before):
private double getUniqueCost(final Node n){
[...]
if(n.isProjection()){
final Node child = n.getChildren().iterator().next();
if(child.isJoin()){
return getUniqueCost(child);
}
final Projection proj = (Projection) n;
return getUniqueCost(proj);
}
throw new IllegalArgumentException("Unknown node type: " + n.getOperator());
}
Given that the cast is executed before actually calling the method (that is, call by value semantics, where the parameters are evaluated before evaluating the method itself), I was expecting it to be sufficient to call the most specific method (the one accepting a parameter of type Projection).
It has been a while since I had a look at the type system of Java, my suspect is that the whole expression child.isJoin() ? n.getChildren().iterator().next() : ((Projection) n) is typed as Node, due to the left part those type is indeed Node.
Does anybody can confirm it? If no, do you have a better understanding of what's going on here?
In addition, is there a way to have a more compact (elegant?) way of writing the second version of the code?
The type of your ternary conditional expression - child.isJoin() ? n.getChildren().iterator().next() : ((Projection) n) - is a type that both n.getChildren().iterator().next() and ((Projection) n) can be assigned to. Therefore, if one of them is Node and the other Projection, assuming Projection is a sub-class of Node, the type of the expression is Node.
Your second snippet can be shortened a bit :
if(child.isJoin()){
return getUniqueCost(child);
} else {
return getUniqueCost((Projection) n);
}
Casting n to Projection is enough the get the overloaded getUniqueCost(final Projection p) method called. You don't need an intermediate variable.

Assign value to method invocation

For later reference:
Operations o = new Operations(); //class containing the operation methods
HashMap<String, Method> ops = new HashMap<String, Method>();
I'm working on a program that will parse a mathematical expression input via console or eventually maybe a GUI.
Currently, I have a class called "Operations" which has various basic math functions (more will be added later, just testing right now). In another class, I have a method which calculates the result by taking an operand, the successive operator, and another operand, and invoking a method to evaluate the expression. It stores the info necessary to the calculation in:
double numOne = //...
char operator = //...
double numTwo = //...
double result = //...
Now I don't want to have a long switch/case statement or if statement saying:
if (operator.equals("+")) //I know .equals() doesn't use chars; it's an example
o.add(numOne, numTwo);
else if (operator.equals("-"))
o.subtract(numOne, numTwo);
on and on for every operation. That's why I tried creating a HashMap<String, Method> to store the operator (String) and the method which should be called. Basically, in the current class' constructor, I put:
ops.put("+", o.getClass().getMethod("add", double.class, double.class));
ops.put("-", o.getClass().getMethod("subtract", double.class, double.class));
//etc. Which in and of itself is also pretty lengthy
Now to once the method is identified via operator, I need another method to return a Method to call.
private Method getMethodFromKey(HashMap<String, Method> map, char op) {
Method method = null;
for (Map.Entry<String, Method> e: map.entrySet()) {
if (e.getKey().equals(op))
method = e.getValue();
}
return method;
}
Finally, once I have the correct method, I can call it with:
getMethodFromKey(ops, operator).invoke(o, numOne, numTwo);
That all works great. My problem is, the method(s) I am/will be invoking are getter methods; they return a double. Example:
public double add(double one, double two) {
double answer = 0;
answer = one + two;
return answer;
}
I guess this is all just a long-winded way of asking is there a way to assign the returned value of an innvoked method? Something like:
result = getMethodFromKey(ops, operator).invoke(o, numOne, numTwo); //This doesn't work :(
Any help is appreciated. Additionally, if my aproach is completely wrong, I would appreciate a bump in the right direction.
DISCLAIMER: I'm relatively inexperienced at Java and known for overcomplicating things, so please point out any grievous flaws in my design. :)
invoke() returns Object and since Java does not know how to assign an Object to a double this won't compile. invoke starts by boxing the double from the method into a Double. You have to cast it now from Object to Double (and could then call .doubleValue() but that's done automatically) for that to work.
I'm [...] known for overcomplicating things, so please point out any grievous flaws in my design. :)
Using reflection instead of an interface. A Method is a function object. But it's not type-safe to use. An interface can do the same without those problems.
interface Operation {
double evaluate(double a, double b);
}
Then put objects that implement the interface in your map:
ops.put("+", new Operation() {
public double evaluate(double a, double b) {
return a+b;
});
and you can do
double result = getMethodFromKey(ops, operator).evaluate(numOne, numTwo);
The need to cast is gone.
If you're sure that all of your operations are going to be on a single class (no extensibility), then you should consider using an enum instead. You can add an instance field to the enum to represent the character command corresponding to the operation and then have an abstract evaluate method that's implemented by each enum value.
If invoke() is returning an Object that you know is a double, you can cast it like so:
result = (Double) getMethodFromKey(ops, operator).invoke(o, numOne, numTwo);
Since double is a primitive, which is not of type Object, you need to cast it to a Double, and through unboxing, we get a double.

Categories