Consider the following method (in Java - and please just ignore the content):
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object == null) {
return false;
}
if (getClass() != object.getClass()) {
return false;
}
if (hashCode() != object.hashCode()) {
return false;
}
return true;
}
I have some plugin that calculates: eV(g)=5 and V(g)=5 - that is, it calculates Essential and common CC.
Now, we can write the above method as:
public boolean equals2(Object object) {
if (this == object) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
return hashCode() == object.hashCode();
}
and this plugin calculates eV(g)=3 and V(g)=3.
But how I do understand CC, the values should be the same! CC is not about counting the lines of code, but the independent paths. Therefore, joining two if in one line does not really reduces CC. In fact, it only can make things less readable.
Am I right?
EDIT
Forgot to share this small convenient table for calculating CC quickly: Start with a initial (default) value of one (1). Add one (1) for each occurrence of each of the following:
if statement
while statement
for statement
case statement
catch statement
&& and || boolean operations
?: ternary operator and ?: Elvis operator.
?. null-check operator
EDIT 2
I proved that my plugin is not working well, since when I inline everything in one line:
public boolean equals(Object object) {
return this == object || object != null && getClass() == object.getClass() && hashCode() == object.hashCode();
}
it returns CC == 1, which is clearly wrong. Anyway, the question remains: is CC reduced
[A] 5 -> 4, or
[B] 4 -> 3
?
Long story short...
Your approach is a good approach to calculate CC, you just need to decide what you really want to do with it, and modify accordingly, if you need so.
For your second example, both CC=3 and CC=5 seem to be good.
The long story...
There are many different ways to calculate CC. You need to decide what is your purpose, and you need to know what are the limitations of your analysis.
The original definition from McCabe is actually the cyclomatic complexity (from graph theory) of the control flow graph. To calculate that one, you need to have a control flow graph, which might require a more precise analysis than your current one.
Static analyzers want to calculate metrics fast, so they do not analyze the control flow, but they calculate a complexity metric that is, say, close to it. As a result, there are several approaches...
For example, you can read a discussion about the CC metric of SonarQube here or another example how SourceMeter calculates McCC here.
What is common, that these tools count conditional statements, just like you do.
But, these metrics wont be always equal with the number of independent execution paths... at least, they give a good estimation.
Two different ways to calculate CC (McCabe and Myers' extension):
V_l(g) = number of decision nodes + 1
V_2(g) = number of simple_predicates in decision nodes + 1
If your goal is to estimate the number of test cases, V2 is the one for you. But, if you want to have a measure for code comprehension (e.g. you want to identify methods that are hard to maintain and should be simplified in the code), V1 is easier to calculate and enough for you.
In addition, static analyzers measure a number of additional complexity metrics too (e.g. Nesting Level).
Converting this
if (hashCode() != object.hashCode()) {
return false;
}
return true;
to this
return hashCode() == object.hashCode();
obviously reduces CC by one, even by your quick table. There is only one path through the second version.
For the other case, while we can't know exactly how your plugin calculates those figures, it is reasonable to guess that it is treating if (object == null || getClass() != object.getClass()) as "if a non-null object's class matches then ...", which is a single check and thus adds just one to CC. I would consider that a reasonable shortcut since null checks can be rolled up into "real" checks very easily, even within the human brain.
My opinion is that the main aim of a CC-calculating IDE plugin should be to encourage you to make your code more maintainable by others. While there is a bug in the plugin (that inlined single-line conditional is not particularly maintainable), the general idea of rewarding a developer by giving them a better score for more readable code is laudable, even if it is slightly incorrect.
As to your final question: CC is 5 if you strictly consider logical paths; 4 if you consider cases you should consider writing unit tests for; and 3 if you consider how easy it is for someone else to quickly read and understand your code.
In the second method
return hashCode() == object.hashCode(); costs 0 so you win 1. It's considered as calculation and not logical branch.
But for the first method I don't know why it's cost 5, I calculate 4.
As far as style is concerned, I consider the following the most readable:
public boolean equals(Object object) {
return this == object || (object != null && eq(this, object));
};
private static boolean eq(Object x, Object y) {
return x.getClass() == y.getClass()
&& x.hashCode() == y.hashCode(); // safe because we have perfect hashing
}
In practice, it may not be right to exclude subclasses from being equal, and generally one can not assume that equal hash codes imply equal objects ... therefore, I'd rather write something like:
public boolean equals(Object object) {
return this == object || (object instanceof MyType && eq(this, (MyType) object));
}
public static boolean eq(MyType x, MyType y) {
return x.id.equals(y.id);
}
This is shorter, clearer in intent, just as extensible and efficient as your code, and has a lower cyclomatic complexity (logical operators are not commonly considered branches for counting cyclomatic complexity).
Related
Hello i have two samples of code
if/else if/else statements
private Object getObj(message) {
if (message.getA() != null)
return message.getA();
else if (message.getB() != null)
return message.getB();
else if (message.getC() != null)
return message.getC();
else return null;
}
Optional statements
private Optional<Object> wrap(Object o){
return Optional.ofNullable(o);
}
private Object getObj(message) {
return wrap(message.getA())
.orElseGet(() -> wrap(message.getB())
.orElseGet(() -> wrap(message.getC())
.orElse(null)));
}
So my question is how these two compare in terms of performance (i have about 15-20 if-else statements on actual code)?
Is it worth refactoring the code readability vs performance or is a misusage of optionals?
Also what is the performance penalty in case the if/else-if statements grown to 100+?
Thanks in advance
Don't use Optionals for conditional logic.
They were designed, to be returned from a method to indicate a potentially absent value.
Just because you can nicely chain them into a single line doesn't mean that it's understandable. Also you literally gain nothing. The performance overhead may be significant. In the worst case N objects being created and then discarded. Just stay with your "normal" if-else chains.
Instead of finding ways to make your current code more readable, take a step back and ask yourself why you need 15-20 if-else statements. Can you split some logic up? Why do you need a getter for so many different fields with potentially different types in the first place? etc.
There is a third form (allowing still some variation).
return Stream.<Supplier<Object>>of(message::getA, message::getB, message::getC)
.map(Supplier::get)
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
Probably the least flexible and efficient at this moment, but clear.
tl;dr
If your goal is condensed code, then use ternary chaining. Performance is likely identical to that of a series of if-then-else statements.
( this.getA() != null ) ? this.getA()
: ( this.getB() != null ) ? this.getB()
: ( this.getC() != null ) ? this.getC()
: null;
Ternary chaining
As the Answer by Lino correctly states, you are trying to take Optional beyond their original design purpose (returning values within lambdas & streams). Generally best to use Optional only with a return statement, and only then when you want to make clear that null is a valid value to be returned. See this Answer by Brian Goetz.
A ternary operator is a condensed if-then-else, combined into a one-liner.
result = test ? valueToUseIfTestIsTrue : valueToUseIfTestIsFalse
Example:
Color color = isPrinterMonochrome ? Color.GREY : Color.GREEN ;
Use a chain of ternary statements.
So this:
if ( this.getA() != null )
return this.getA();
else if ( this.getB() != null )
return this.getB();
else if ( this.getC() != null )
return this.getC();
else return null;
…becomes this:
return
( this.getA() != null ) ? this.getA()
: ( this.getB() != null ) ? this.getB()
: ( this.getC() != null ) ? this.getC()
: null;
Example code.
public String getA ()
{
// return "A";
return null;
}
public String getB ()
{
// return "B";
return null;
}
public String getC ()
{
return "C";
// return null;
}
public String getABC ()
{
if ( this.getA() != null )
return this.getA();
else if ( this.getB() != null )
return this.getB();
else if ( this.getC() != null )
return this.getC();
else return null;
}
public String getABCTernary ()
{
return
( this.getA() != null ) ? this.getA()
: ( this.getB() != null ) ? this.getB()
: ( this.getC() != null ) ? this.getC()
: null;
}
Run that example code.
String s = this.getABCTernary();
System.out.println( "s: " + s );
C
Pros and cons
The upside to the ternary chain is condensed code, collapsed into a one-liner.
The downside is that you are calling your getter method twice in this particular situation just to get a single value. Not a problem for a simple fetch-the-variable kind of getter, but impact performance if the getter is a time-consuming method such as a remote web services call. And, the cascading if-then-else has the same problem, also calling your getter twice.
Performance
how these two compare in terms of performance
The ternary operator in Java is "short-circuiting", meaning the left or right side that matches the test results is the only code called. In our code here, if getA returns a non-null value, that value is returned immediately. The further calls to getB and getC are never executed. So in this regard, the performance of the chained ternary is the same as a cascading if-then-else statement: first-match wins, no further calls.
If you mean performance as in nanoseconds of execution, I do not know. Worrying about that would be falling into the trap of premature optimization. Modern JVMs are extremely well-tuned for optimizing your code.
In my opinion after around 20 years of commercial experience, I've formed a view that pursuing readability is absolute stupidity, and at the same time, intentionally writing convoluted code is evil.
I know this goes totally against popular opinion.
However, everyone needs to realize this...
What is readable to one person is not necessarily readable to the next. Even in this thread, we have varying opinions of whether if or Optional are more readable or not. These kinds of debates will occur irrespective of what constructs or situations we are in.
If we take the if option, which is more performant than the functional approach, each and every time, then the people reading that code will get used to it and find it MORE READABLE - because it is the style that they have now become accustomed to.
Performant code does not have to be "hard to read"... but this loops back to points 1 and 2. It's a matter for developers to actually know the fundamentals of the language they are using, and writing the code appropriate for that language, rather than trying to form "english sentences" in their code.
So, in essence: go with the if... do NOT use that Optional!
A couple of days ago I ran a thorough performance analysis. There's a huge performance impact. With AdoptOpenJDK, if statements are up to 10 times faster. When the JIT compiler runs hot, this reduces to a 20% penalty.
GraalVM does a better job: 3 times slowdown with the cold JVM, and after giving the compiler enough time to do its magic, there's also a 20% performance penalty.
However, the real question is which version is better for reading and maintaining the application. If you're like me, it's easier to read the if statement, but there are also people preferring the functional approach.
If you're ready for a deep, deep dive, I invite you to read my detailed analysis about the performance and the implementation of Optional.orElseGet() and its friends.
I've never had occasion to write a hashcode function in Java but now I have a need to do so. How do I go about it?
It's for an ArrayList and each element contains 5 Strings and nothing else.
I found an example for an ArrayList that contains 2 string and it's very simple:
return 31 * lastName.hashCode() + firstName.hashCode();
Can I get away with something equally simple, namely:
return 31 * field1.hashcode() + field2.hashcode() + field3.hashcode() + field4.hashcode() + field5.hashcode();
Or does a hashcode() method have further requirements?
I found another StackOverflow discussion of hashcode() here: Best implementation for hashCode method
From that, I imitated one of the answers and came up with this:
return Objects.hash(this.mClientCode, this.mOrderNumber, this.mOrderDate, this.mTicketsSold, this.mSellerName);
Is that better than the first one I suggested? Why?
Since hashcode() and equals() should apparently always get changed at the same time, this is my equals():
public boolean equals(Object o) {
if (!(o instanceof SalesItem)) {
return false;
}
SalesItem n = (SalesItem) o;
return n.mClientCode.equals(mClientCode) && n.mOrderNumber.equals(mOrderNumber) &&
n.mOrderDate.equals(mOrderDate) && n.mTicketsSold.equals(mTicketsSold) &&
n.mSellerName.equals(mSellerName);
}
Does that look okay?
Your equals is almost right. If none of those values can be null, its good. If they can be, then you need to add null checks as well- if((n.lastName!= null && n.lastName.equals(lastname)) || (n.lastName == null && lastname == null)) and repeat for the others.
For the hash- what you want is the has to be as randomly distributed as possible and unique for the values you would consider unique. Its hard for us to tell you a good hash algorithm because we don't know how your data structure is used. For example, if there's only 4 sellers, you'd want that field to be a very small factor in the hash, if a factor at all.
Is this a representation of a database row? It looks like one. Because if it is, the rowId or a UUID for the row would be the best thing to hash.
You can also use the HashCodeBuilder in the org.apache.commons.lang3 library.
Here is the documentation and an example:
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/HashCodeBuilder.html
I've got a Java class, here's an example:
public class Car {
private int fuelType;
private Date made;
private String name;
.
.
. // and so on
Now let's say I have two car objects and I want to compare if all their variables are equal.
Right now, I've solved this by overriding method equals(Object o) and I check if all the variables match in both objects.
The problem here is that if I have 20 classes, I'll have to override equals(Object o) in every single one of them.
Is there a way create some sort of universal method that could compare any of the two objects that I pass to it and let me know if they match in every single variable or not?
You have a few options for automating Equals & Hashcode (option #3 BLEW MY MIND!):
Your IDE. I would not recommend it for most objects as they can slowly drift out of date with the actual class definition. They also look ugly and pollute your codebase with boilerplate code.
Apache Commons has a bunch of stuff for making this easier, including a reflective version so no risk of drifting out of date with the class definition. It is better than #1 unless you require a speedy equals/hashcode, but still too much boilerplate for my liking.
Project Lombok and annotation processing. Whack an EqualsAndHashCode annotation on ya class and be done with it. I recommend using Project Lombok. It adds a touch of magic into the build (but not much) and so requires a plugin for your IDE to behave nicely but they are a small price to pay for no boilerplate code. Lombok is an annotation processor that run at compile time so you have no runtime performance hit.
Using a different language that supports it out the box, but also targets the JVM. Groovy uses an annotation and Kotlin supports data classes. Unless your existing code can quickly be converted, I would avoid this.
Google's Auto has an AutoValue. Like Project Lombok this is an annotation processor, however has less magic at the expense of little more boilerplate (thanks to Louis Wasserman)
you can use :
org.apache.commons.lang.builder.CompareToBuilder.reflectionCompare(Object lhs, Object rhs);
it uses reflection to compare the fileds
here is the javadoc : javadoc
I'll take the dissenting opinion to the majority (use apache commons with reflection) here: Yes, this is a bit code you have to write (let your IDE generate really), but you only have to do it once and the number of data classes that need to implement equals/hashcode is generally rather manageable - at least in all of the large projects (250k+ LOC) I worked on.
Sure if you add a new member to the class you will have to remember to update the equals/hashcode functions, but that's generally easy to notice, at the latest during code reviews.
And honestly if you use a simple little helper class that's even in Java7, you can cut down the code that Wana Ant showed immensely. Really all you need is:
#Override
public boolean equals(Object o) {
if (o instanceof Car) { // nb: broken if car is not final - other topic
Car other = (Car) o;
return Objects.equals(fuelType, other.fuelType) &&
Objects.equals(made, other.made) &&
Objects.equals(name, other.name);
}
return false;
}
similar for hashcode:
#Override
public int hashCode() {
return Objects.hash(fuelType, made, name);
}
Not as short as the reflection solution? True, but it's simple, easy to maintain, adapt and read - and performance is orders of magnitude better (which for classes that implement equals and hashcode is often important)
Typically you can generate equals/hashCode methods by your IDE - all big players in this field are capable of that (Eclipse, IntelliJ Idea and Netbeans).
Generally you can create some code that will use reflection but I don't recommend this one as objective approach is clearer and more maintainable. Also reflection won't be as fast as "standard" way. If you really want to go this way, there exist utilities like EqualsBuilder and HashCodeBuilder.
Just for your information, there are JVM-based languages that already support these features, e.g. Kotlin data classes, which can be pretty nicely used in existing Java projects.
I'll just throw in a plug for my favorite solution to this problem: #AutoValue.
This is an open-source project from Google that provides an annotation processor that generates a synthetic class that implements equals and hashCode for you.
Since it's auto-generated code, you don't have to worry about accidentally forgetting a field or messing up the equals or hashCode implementation. But since the code is generated at compile time, there's zero runtime overhead (unlike reflection-based solutions). It's also "API-invisible" -- users of your class can't tell the difference between an #AutoValue type and a type you implemented yourself, and you can change back and forth in the future without breaking callers.
See also this presentation which explains the rationale and does a better job comparing it to other approaches.
Theoretically you could use reflection to create some kind of util, as many people suggest you in comments. Personally I don't recommend you to do it. you will end up with something which is partially working.
Many things in Java rely on equal or hashCode, for example method contains which you can find in anything which implements Collection.
Overriding equal (and hashCode) is recommended solution. By addition, i think any decent IDE will have option to generate them for you. Hence you can do it quicker than by using reflection.
That's the way I would do it:
#Override
public boolean equals(Object obj) {
if (obj instanceof Car) {
return internalEquals((Car) obj);
}
return super.equals(obj);
}
protected boolean internalEquals(Car other) {
if(this==other){
return true;
}
if (other != null) {
//suppose fuelType can be Integer.
if (this.getFuelType() !=null) {
if (other.getFuelType() == null) {
return false;
} else if (!this.getFuelType().equals(other.getFuelType())) {
return false;
}
} else if(other.getFuelType()!=null){
return false;
}
if (this.getName() != null) {
if (other.getName() == null) {
return false;
} else if (!this.getName().equals(other.getName())) {
return false;
}
}
else if(other.getName()!=null){
return false;
}
if (this.getDate() != null) {
if (other.getDate() == null) {
return false;
} else if (!this.getDate().getTime()!=(other.getDate().getTime())) {
return false;
}
}
else if(other.getDate()!=null){
return false;
}
return true;
} else {
return false;
}
}
EDIT
Simplified version
public class Utils{
/**
* Compares the two given objects and returns true,
* if they are equal and false, if they are not.
* #param a one of the two objects to compare
* #param b the other one of the two objects to compare
* #return if the two given lists are equal.
*/
public static boolean areObjectsEqual(Object a, Object b) {
if (a == b){
return true;
}
return (a!=null && a.equals(b));
}
public static boolean areDatesEqual(Date a, Date b){
if(a == b){
return true;
}
if(a==null || b==null){
return false;
}
return a.getTime() == b.getTime();
}
}
#Override
public boolean equals(other obj) {
if(this == other){
return true;
}
if(other == null){
return false;
}
if (other instanceof Car) {
return internalEquals((Car) other);
}
return super.equals(obj);
}
protected boolean internalEquals(Car other) {
//suppose fuelType can be Integer.
if (!Utils.areObjectsEqual(this.getName(), other.getName()){
return false;
}
if (!Utils.areObjectsEqual(this.getName(), other.getName()){
return false;
}
if (!Utils.areDatesEqual(this.getDate(), other.getDate()){
return false;
}
return true;
}
}
Also don't forget about hashcode, they code hand in hand.
Our team's Java Coding Guideline says:
Avoid using "!" in if statement as much as possible.
I have asked other colleagues, but no one gave me clear ideas why, because the guideline was created a long time ago and the author might have left our company.
Do you have any idea?
With the information provided, this calls for some speculation. One possible reason is that the intent was not for an if-statement by itself but for an if-else statement. In that case, I can see where you might say that you should reverse the cases so that you don't have the extra operation of the negation. Instead of
if (! boolVar) {
// Something
} else {
// Something else
}
you might prefer
if (boolVar) {
// Something else
} else {
// Something
}
Whether this is worth it or not is probably more a matter of taste and standardization than anything else.
The rule is likely an adaptation from Robert Martin's Clean Code, page 302:
Negatives are just a bit harder to understand than positives. So, when possible, conditionals should be expressed as positives. For example:
if(buffer.shouldCompact())
is preferable to
if(!buffer.shouldNotCompact())
As an example, suppose you're creating a validator that requires two things to be false for the entity to be valid:
The entity must not have been created within the last 12 hours, and
The entity's bank account total sum must not exceed $50,000.
Naturally the idea would be to write two methods for this:
boolean isCreatedWithinLastTwelveHours(BankAccount account)
boolean hasMoreThanTotalSumCap(BankAccount account)
...at which point, you then invoke these as:
boolean newAccount = isCreatedWithinTheLastTwelveHours(account);
boolean highEndAccount = hasMoreThanTotalSumCap(account);
if(!newAccount && !highEndAccount) { // ... other logic
// The more astute would use DeMorgan's law in an effort to make this more readable
if(!(newAccount || highEndAccount)) { // other logic
Well...wouldn't it be nicer if you just said what they weren't instead?
boolean isNotCreatedWithinLastTwelveHours(BankAccount account)
boolean hasLessThanTotalSumCap(BankAccount account)
That'd make the expression a bit more concise:
if(notNewAccount && notHighEndAccount) { // .. carry on!
Of course "!" can be used when you like. There is no "unless" in java and you have no other choices in some conditions.
Looks like yet-another-useless-rule. Generally speaking, there are no absolute terms in this scenario, true that if you are in a if-else clause then possibly it is better to write
if(myCondition) {
doThis()
} else {
doSomethingElse()
}
Instead of
if(!myCondition) {
doSomethingElse()
} else {
doThis()
}
However, that said, in some scenarios is actually quite ok to use the negation operator, particularly if no else clause is provided, example
if (!tokenDoesCompute()) {
throw InvalidTockenException("Whatever")
}
And actually in that scenario, using "!" makes quite a bit of sense for me.
Finally, if no one can really explain WHY the rule is there, maybe it is time to remove it, the only good reason I could find for it would be to provide consistency regarding the code style.
Okay, I answer my own question.
As other say, maybe this is written for the readability.
In The Art of Readable Code (p. 72) says:
Prefer dealing with the positive case first instead of the negative-e.g., if(debug) instead of if(!debug)
I found below post as well:
Readable Code - Remove Checking null
bool func(String name)
{
if ( (name != null) && (name.equals("true") ) {
//...
} else {
//...
}
}
bool func(String name)
{
if ( "true".equals(name) ) {
//...
} else {
//...
}
}
Ofcourse you can use the negation operator ! whenever you like.
However, if you have a situation where you have to write some actions in both if and else block then the following is more readable :
if(status){
//do something
}
else{
//do something else
}
than
if(!status){
//do something
}
else{
//do something else
}
But if you have situation where you only need to perform certain actions based on just one condition, i.e. if you have only an if block & no else block, then it is reasonably fine to use ! in if
I haven't seen anyone else suggest this, which is probably because they hate it as much as I do, but I'm showing it for completeness.
// Using not operator (preferred)
if (! someTest) { ... }
// Using compact not operator (kind of hides it)
if (!someTest) { ... }
// Comparing to false (ok, explicitly states what you want)
if (someTest == false) { ... }
// Comparing to true (a bit obscure)
if (someTest != true) { ... }
They all do the same, but please keep using !, just make sure you add a space after it, so it's easier to see.
Assume that we have a given interface:
public interface StateKeeper {
public abstract void negateWithoutCheck();
public abstract void negateWithCheck();
}
and following implementations:
class StateKeeperForPrimitives implements StateKeeper {
private boolean b = true;
public void negateWithCheck() {
if (b == true) {
this.b = false;
}
}
public void negateWithoutCheck() {
this.b = false;
}
}
class StateKeeperForObjects implements StateKeeper {
private Boolean b = true;
#Override
public void negateWithCheck() {
if (b == true) {
this.b = false;
}
}
#Override
public void negateWithoutCheck() {
this.b = false;
}
}
Moreover assume that methods negate*Check() can be called 1+ many times and it is hard to say what is the upper bound of the number of calls.
The question is which method in both implementations is 'better'
according to execution speed, garbage collection, memory allocation, etc. -
negateWithCheck or negateWithoutCheck?
Does the answer depend on which from the two proposed
implementations we use or it doesn't matter?
Does the answer depend on the estimated number of calls? For what count of number is better to use one or first method?
There might be a slight performance benefit in using the one with the check. I highly doubt that it matters in any real life application.
premature optimization is the root of all evil (Donald Knuth)
You could measure the difference between the two. Let me emphasize that these kind of things are notoriously difficult to measure reliably.
Here is a simple-minded way to do this. You can hope for performance benefits if the check recognizes that the value doesn't have to be changed, saving you an expensive write into the memory. So I have changed your code accordingly.
interface StateKeeper {
public abstract void negateWithoutCheck();
public abstract void negateWithCheck();
}
class StateKeeperForPrimitives implements StateKeeper {
private boolean b = true;
public void negateWithCheck() {
if (b == false) {
this.b = true;
}
}
public void negateWithoutCheck() {
this.b = true;
}
}
class StateKeeperForObjects implements StateKeeper {
private Boolean b = true;
public void negateWithCheck() {
if (b == false) {
this.b = true;
}
}
public void negateWithoutCheck() {
this.b = true;
}
}
public class Main {
public static void main(String args[]) {
StateKeeper[] array = new StateKeeper[10_000_000];
for (int i=0; i<array.length; ++i)
//array[i] = new StateKeeperForObjects();
array[i] = new StateKeeperForPrimitives();
long start = System.nanoTime();
for (StateKeeper e : array)
e.negateWithCheck();
//e.negateWithoutCheck();
long end = System.nanoTime();
System.err.println("Time in milliseconds: "+((end-start)/1000000));
}
}
I get the followings:
check no check
primitive 17ms 24ms
Object 21ms 24ms
I didn't find any performance penalty of the check the other way around when the check is always superfluous because the value always has to be changed.
Two things: (1) These timings are unreliable. (2) This benchmark is far from any real life application; I had to make an array of 10 million elements to actually see something.
I would simply pick the function with no check. I highly doubt that in any real application you would get any measurable performance benefit from the function that has the check but that check is error prone and is harder to read.
Short answer: the Without check will always be faster.
An assignment takes a lot less computation time than a comparison. Therefore: an IF statement is always slower than an assignment.
When comparing 2 variables, your CPU will fetch the first variable, fetch the second variable, compare those 2 and store the result into a temporary register. That's 2 fetches, 1 compare and a 1 store.
When you assign a value, your CPU will fetch the value on the right hand of the '=' and store it into the memory. That's 1 fetch and 1 store.
In general, if you need to set some state, just set the state. If, on the otherhand, you have to do something more - like log the change, inform about the change, etc. - then you should first inspect the old value.
But, in the case when methods like the ones you provided are called very intensely, there may be some performance difference in checking vs non-checking (whether the new value is different). Possible outcomes are:
1-a) check returns false
1-b) check returns true, value is assigned
2) value is assigned without check
As far as I know, writing is always slower than reading (all the way down to register level), so the fastest outcome is 1-a. If your case is that the most common thing that happens is that the value will not be changed ('more than 50%' logic is just not good enough, the exact percentage has to be figured out empirically) - then you should go with checking, as this eliminates redundant writing operation (value assignment). If, on the other hand, value is different more than often - assign it without checking.
You should test your concrete cases, do some profiling, and based on the result determine the best implementation. There is no general "best way" for this case (apart from "just set the state").
As for boolean vs Boolean here, I would say (off the top of my head) that there should be no performance difference.
Only today I've seen few answers and comments repeating that
Premature optimization is the root of all evil
Well obviously one if statement more is one thing more to do, but... it doesn't really matter.
And garbage collection and memory allocation... not an issue here.
I would generally consider the negateWithCheck to be slightly slower due there always being a comparison. Also notice in the StateKeeperOfObjects you are introducing some autoboxing. 'true' and 'false' are primitive boolean values.
Assuming you fix the StateKeeperOfObjects to use all objects, then potentially, but most likely not noticeable.
The speed will depend slightly on the number of calls, but in general the speed should be considered to be the same whether you call it once or many times (ignoring secondary effects such as caching, jit, etc).
It seems to me, a better question is whether or not the performance difference is noticeable. I work on a scientific project that involves millions of numerical computations done in parallel. We started off using Objects (e.g. Integer, Double) and had less than desirable performance, both in terms of memory and speed. When we switched all of our computations to primitives (e.g. int, double) and went over the code to make sure we were not introducing anything funky through autoboxing, we saw a huge performance increase (both memory and speed).
I am a huge fan of avoiding premature optimization, unless it is something that is "simple" to implement. Just be wary of the consequences. For example, do you have to represent null values in your data model? If so, how do you do that using a primitive? Doubles can be done easily with NaN, but what about Booleans?
negateWithoutCheck() is preferable because if we consider the number of calls then negateWithoutCheck() has only one call i.e. this.b = false; where as negateWithCheck() has one extra with previous one.