Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I read in a book (Fischer's Java Closures and Lambda, Apress 2015) that method references are preferable to lambda expressions. From my point of view, the lambda expression is more easily understandable to developers who use other languages. Then why does it say the method reference is preferable? Is writing a lambda expression a bad practice in Java 8?
In the Lambda Best Practices section of Chapter 2, Fischer's book says:
As much as possible, use a method reference instead of a lambda. Method references are not only shorter and easier to read, but using method references will get you thinking directly about the methods as values. This is the code you need to excise from your codebase and your brain:
x -> it.do(x)
If you are naturally writing that code, then you still have not made the leap to thinking at the higher level of functional programming. Once you make that leap, it will become much easier to communicate and work with complex functions, because you will be thinking in types, not in values.
Although I mostly agree with the conclusion, I'm not sure I buy Fischer's line of reasoning. Method references are often, though not always, shorter than the written-out lambda. In the first part he says that method references will help you think about methods as values. OK, but then later he says things will become easier because you'll be thinking in types, not values. I'm not sure what that means.
It's possible to rewrite the example expression he gives as
it::do
That's certainly shorter than the original, but it's hard to generalize from a tiny example.
Here's my take on method references vs. written-out lambdas.
If there is a choice between using a lambda expression and a method reference, it is often the case that a method reference is preferable. But this is not a hard-and-fast rule, and there are likely to be circumstances where a lambda expression is preferable. It's also somewhat a matter of taste.
If you're familiar with lambda expressions from other languages, then lambda expressions in Java will probably be more immediately familiar than method references. However, I believe this to be a temporary state until you learn method references. Once they're more familiar, the advantages of method references can outweigh the initial unfamiliarity.
Consider this simple example of getting the lengths of strings:
List<String> list = ... ;
int[] lengths1 = list.stream().mapToInt(s -> s.length()).toArray();
int[] lengths2 = list.stream().mapToInt(String::length).toArray();
In this case, the size of the lambda expression is just about the same as the size of the method reference (in the number of characters). But notice that the method reference contains more type information. It tells the reader that the element type is String, which may be helpful in understanding a long pipeline. It is sometimes also helpful to the compiler, if it cannot infer the element type, as sometimes occurs in complex expressions.
Another point is that, using a method reference will often relieve you of the responsibility of coming up with a name for a formal parameter that's simply passed to another method. Naming is often important, but lambda formals are often "garbage" names like i x or s as in this example.
The method reference is a tiny bit more efficient, as it doesn't need to generate a static method that must be called through to get to the String.length() method. But this efficiency is rarely an important consideration.
Consider also this example, deliberately stripped of context:
(x, y) -> x + y
Is this string concatenation or numeric addition? If numeric, what type? Under the rules of the language, this must be known at compile time, otherwise it's an error. Although it might be clear to the compiler, sometimes this isn't very clear to the reader. Consider instead these method references:
String::concat
Integer::sum
Double::sum
Using a name for the operation in this case makes it very explicit to the reader about what is intended.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
do you prefer writing method with immediate return of result to assigning it firstly to variable? To be clear we only consider situation presented below when no other operations are done in method body.
First option:
private List<Integer> getIdsOfUsersLoggedWithinLastHour() {
return userDAO.getUsersLoggedWithinLastHour().stream().map(User::Id).collect(Collectors.toList());
}
Second option:
private List<Integer> getIdsOfUsersLoggedWithinLastHour() {
List<Integer> ids = userDAO.getUsersLoggedWithinLastHour().stream().map(User::Id).collect(Collectors.toList());
return ids;
}
IMHO there is no need to assign result of method operations to variable when you do nothing with it and just return. The return type is declared in method signature so you can easily check it. The code cleanliness is about the same. You use some additional memory and cpu operations (maybe not so important today but it is always something additional). Friend of mine claims that initializing variable is better for easier debugging and further code development but I think it is redundant and can be done when you really need this, not 'for future'. What is your opinion?
In many cases I plump for the second option and, in the cited case, I almost certainly would.
This allows you to place a breakpoint on return ids; which can be helpful when debugging. (Inspecting the contents of a CPU register is an option in low level languages like C, but I don't think that is available for JVM-based languages).
A series of functions that return an anonymous temporary up the stack can be difficult to debug.
I wouldn't worry about any overhead that the second choice introduces: that ought to be optimised out and declaring an extra reference variable is unlikely to cause a performance bottleneck even if it was not optimised out. (Note that in C++ it will be optimised out via a process called Named Return Value Optimisation and I imagine that Java would follow suit.) Remember that being able to debug and maintain code is as important as elegance; whatever that means in this particular instance.
I assign result to the variable only when need to do some logic with it before returning value from the method. Otherwise I use coding style from the first example - makes code concise.
Second code style can help during debug process sometimes, but you shouldn't commit this IMHO
Also, if you inspect second example with any popular static analysis tool it would give a result like "local variable is redundant" which is one more reason to eliminate those vars in real projects.
Good article about this design issue: http://www.yegor256.com/2015/09/01/redundant-variables-are-evil.html
But you must understand that it's only a common practice, nobody can make you do not use redundant variables - code works with them correctly, it's only a question of taste like many other design principles
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
For example in the case of an anonymous inner class, an (anonymous) object reference is passed and methods of that object are executed.
Lambdas are code blocks which will be executed when needed.
What happens in the JVM when lambdas are encountered? Where does the JVM store the code blocks related to lambdas (Heap : Young, Old or Permanent Generation)?
I tried searching, and I got the syntax for using lambdas but was not able to understand what is happening inside JVM, as in JAVA everything is object-based.
So in context of OOP how do lambdas work?
Do lambdas violate OOP concepts?
Is Lambda good for the garbage collector as no objects are created hence
no worry about memory issues and clearing memory?
I wouldn't waste my time thinking whether the lambda expressions are a violation of OO principles. Its goal is to increase the power of a language and not to write an OO code, I don't see how lambdas can violate encapsulation, inheritance or polymorphism.
This article explains how Java handles lambda expressions:
What’s interesting about Lambda expressions is that from the JVM’s perspective they’re completely invisible. It has no notion of what an anonymous function or a Lambda expression is. It only knows bytecode which is a strict OO specification. It’s up to the makers of the language and its compiler to work within these constraints to create newer, more advanced language elements.
Considering the following code:
List names = Arrays.asList("1", "2", "3");
Stream lengths = names.stream().map(name -> name.length());
... It begins quite simply by loading the names var and invokes its .stream() method, but then it does something quite elegant. Instead of creating a new object that will wrap the Lambda function, it uses the new invokeDynamic instruction which was added in Java 7 to dynamically link this call site to the actual Lambda function.
aload_1 //load the names var
// call its stream() func
invokeinterface java/util/List.stream:()Ljava/util/stream/Stream;
//invokeDynamic magic!
invokedynamic #0:apply:()Ljava/util/function/Function;
//call the map() func
invokeinterface java/util/stream/Stream.map:
(Ljava/util/function/Function;)Ljava/util/stream/Stream;
InvokeDynamic is an instruction that was added in Java 7 to make the JVM less strict, and allows dynamic languages to bind symbols at run-time, vs. doing all the linkage statically when the code is compiled by the JVM.
The Lambda code
aload_0
invokevirtual java/lang/String.length:()
invokestatic java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
areturn
Lambda expressions don't get translated into anonymous inner classes, they use invoke dynamic that was introduced in Java 7 to execute functional methods. Check this out.
Do they violate OOP? I don't think that you should care. Lambdas make your code less verbose, easier to understand, and "easier" to parallelise. And thats what you should care about.
From Brain Goetz comment:
We don't get paid to write object-oriented programs or functional programs, we get paid to write working programs.
Lambda expression is compiled using invokedynamic bytecode.
Lambda implementation is stored in the same class file as a special private method.
Whether an object is created to invoke lambda depends on the situation. In the trivial cases lambda gets translated to a constant method handle.
To instantiate a lambda HotSpot creates an anonymous class that implements lambda's functional interface. This class does not belong to any ClassLoader.
See more details from the specification lead of Lambda Expressions JSR.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I've seen some legacy code that uses lengthproperty on some objects and others that uses length() method. Currently I'm working with a NodeList from the org.w3c.dom package and I found that it have the getLength() method to get the numbers of elements.
My Question is how as Java developer I can know how to determine when to use length, length(), size(), getLength()? obviously it depends of the object type and the API is there for read... but the point is how the Java Development select which of that implements in their classes.
Note: In the Question When to use .length vs .length() Makoto answer's indicates that .length is a property on arrays. That isn't a method call, and length() is a method call on String. But, why is the reason? why not use ever a method or ever a property for maintain the consistency around all the API.
how would Java developers select which of [the methods] to implement in their classes?
When you implement classes that contain other objects, it's almost always going to be size(), the method provided by theCollection interface.
As far as other choices go, you should avoid exposing member variables, even final ones, because they cannot be accessed through an interface. Java gets away with it for arrays because of some JVM trickery, but you cannot do the same. Hence, length should be out: it remains in Java because it's not possible to change something that fundamental that has been in the language from day one, but it's definitely not something one should consider when designing new classes.
When you implement your own type that has length (say, a rectangle or a line segment) you should prefer getLength() to length() because of Java Beans naming conventions.
obviously it depends of the object type and the API is there for read...
You already have answered your question yourself: look in the API documentation of whatever class you are using.
but the point is how the Java Development select which of that implements in their classes.
The classes in Java's standard library have been developed over a long period of time by different people, which do not always make the same choice for the name of methods, so there are inconsistencies and unfortunately you'll just have to live with that.
There is no clear rule, otherwise we wouldn't see such a mixup in the jdk itself. But here are some things to consider when making such a design decision.
Don't worry to much. It is a minor thing and won't make to much of a difference. So when you think longer then 5 minutes about this, you are probably wasting money already.
Use getters when a frameworks need them. Many frameworks depend on the getter style. If you need or want such frameworks to work nicely with your class it might be beneficial to use that style.
Shorter is better. the 'get' part doesn't increase clarity. It just generates to characters of noise to the source code, so if you don't need it for some reason, don't use it.
Methods are easier to evolve. Length is often a quantity that is not set directly but somehow computed. If you hide that behind a method it gives you the flexibility to change that implementation later on, without changing the API.
Direct field accesses should be a tiny bit faster, but if you aren't working on high volume online trading or something, the difference isn't even worth thinking about. And if you do you should do your own measurements before making a decision. The hotspot compiler will almost for sure inline the method call anyways.
So if there aren't any external forces driving you in a different direction I would go with 'length()'
According to OOPS principles, length should be attribute and getLength() should be method. Also length attribute should be encapsulated should be exposed through methods, so getLength() sounds more appropriate.
Unfortunately not all Java library classes follow standards. There are some exceptions and this is one among them.
In a pure OO language it should be probably always a method like length(). So in a class hierarchy you can override the attribute length.
But Java is not pure OO. And the main reason for fields (.length) vs method (length()) is/was performance issues.
And even Sun/Oracle programmers did some bad class design.
So Java 8 introduces method references and the docs describe the four types.
My question is what's the difference between the two instance types?
Reference to an instance method of a particular object.
Reference to an instance method of an arbitrary object of a particular type.
Both refer to references but what's significantly different? Is it that the type inference used to resolve them is different? Is it significant that (in their examples) one is a closure and the other is a lambda? Is it something to do with the number of arguments on a method?
myString::charAt would take an int and return a char, and might be used for any lambda that works that way. It translates, essentially, to index -> myString.charAt(index).
String::length would take a String and return an int. It translates, essentially, to string -> string.length().
String::charAt would translate to (string, index) -> string.charAt(index).
With this they mean that you have the following:
1) Can be for example this::someFunction;, this will return the someFunction reference of the current object.
2) Can be for example String::toUpperCase, this will return the toUpperCase method of String in general.
I am not sure if there is an actual difference in behaviour, I think it is just like you can also call static methods on instance variables.
I wrote up the conclusion I came to here, the following is a summary.
Oracle describe the four kinds of method reference as follows.
What they should have written is:
I found their description of the first two confusing ("reference to a static method" and "reference to an instance method of a particular objects"), I think its really the difference between a class static and an object.
I prefer to think of the first as an instance method of a specific object known ahead of time and the second as an instance method of an arbitrary object that will be supplied later. Interestingly, this means the first is a closure and the second is a lambda. One is bound and the other unbound.
The distinction between a method reference that closes over something (a closure) and one that doesn’t (a lambda) may be a bit academic but at least it’s a more formal definition than Oracle’s unhelpful description. If you’re interested in the difference between a closure and a lambda, check out this post.
Summary
The difference between the two types of instance method reference is interesting but basically academic. Sometimes, you’ll need to pass something in, other times, the usage of the lambda will supply it for you. My gripe is with Oracle’s documentation. They make a big deal out of the distinction but fail to describe it in an easily understandable way. It’s the canonical reference material but it’s just plain confusing.
There's one or two more subtleties to it that I wrote up.
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 9 years ago.
Improve this question
In Java, say I have an expression X that occurs multiple times in a function. Generally speaking, is it more efficient to create a variable and set it equal to X, or not use a variable at all? What are the advantages/disadvantages of each method?
Ex. Say X = 5+9*9-1000. Which function is more efficient, function1 or function2?
public void function1() {
System.out.println(5+9*9-1000);
System.out.println(5+9*9-1000);
}
public void function2() {
int variable = 5+9*9-1000;
System.out.println(variable);
System.out.println(variable);
}
Neither is more efficient. Your expression 5+9*9-1000 is a constant expression. The compiler will evaluate it at compile time and only the result shows up at runtime (-914).
The JLS defines constant expressions in Section 15.28. Basically it consists of literals, operators, and constant variables.
Often it's more convenient, readable, and expressive to have a constant expression rather than multiplying the values yourself.
int secondsPerDayCalc = 86400; // not obvious it's number of seconds in a day
int secondsPerDay = 60 * 60 * 24; // constant expression; more readable
There is no performance penalty, because it's evaluated at compile time.
Use a variable in this case or a function in more complicated cases. Yes, there may be an efficiency gain, but the real issue is the maintainability of the code. Repeated strings of characters like this create a source of potential errors if the expressions need to change.
Generally speaking, is it more efficient to create a variable and set it equal to X, or not use a variable at all?
Generally speaking, it is not possible to say. It may be more efficient. It may make no difference. It could conceivably even be less efficient. It all depends on what the JIT compiler does with the code, and that is dependent on the JVM you are using, the application, and even the input data.
(In your specific example, the expressions are constant expressions, and they will be evaluated at compile time. That makes the runtime efficiency issue moot.)
What are the advantages/disadvantages of each method?
To my mind, the most important issues are:
Readability. Splitting an expression into sub-expressions with temporary variables may make your code more readable. (It depends on the code complexity ... and the expected Java reading skills of the people who need to maintain your code.)
Side-effects. Some expressions involve side-effects. In this case, refactoring to use temporary variables may change the meaning of the computation.
The best general advice is to leave this kind of optimization to the JIT compiler. But if performance is an critical issue, and you do really need to optimize at this level, then you need to do it scientifically.
Benchmark your code (properly!) to establish a performance baseline.
Profile it to identify hotspots.
Modify the code to improve performance at a hotspot.
Rerun the benchmark to see if you have improved things.
Go to step two ...
(Optimizing based solely on your intuition, you are liable waste a lot of your time optimizing with minimal measurable performance benefits. Also bear in mind that hand optimizing for one platform does not necessarily improve performance on others ...)