Is that how 'Long' works (in Java)?
Look at this Java code:
class PerformanceTest2{
public static void main(String args[]){
Long sum = 0L;
for(int i=0;i<Integer.MAX_VALUE;i++)
sum += i;
Sy开发者_StackOverflow中文版stem.out.println("Sum = " + sum);
}
}
It is observed that it takes longer for this code since sum is 'Long' & not 'long'. So in every iteration what happens is:
sum = new Long(sum.longValue() + i); (for sum+=i;)
So, a new object is created every time. Doesn't Java support C++ like feature of returning a reference so that we could've written (possibly):
sum.longValue() += i;
possibly not having to create sum object every time around the loop? Am I right?
Well, it doesn't call the constructor. It uses:
for (int i = 0; i < Integer.MAX_VALUE; i++)
{
long tmp = sum.longValue(); // Unboxing
tmp += i;
sum = Long.valueOf(tmp); // Boxing
}
The wrapper objects are deliberately immutable - they could easily have been designed to be mutable, but immutability is often a very useful feature. If you want to write your own mutable wrapper type, you're very welcome to - at which point you could have code such as:
LongWrapper sum = new LongWrapper(0L);
for (int i = 0; i < Integer.MAX_VALUE; i++)
{
sum.add(i);
}
System.out.println("Sum = " + sum);
Or possibly:
LongWrapper sum = new LongWrapper(0L);
for (int i = 0;i < Integer.MAX_VALUE; i++)
{
sum.setValue(sum.getValue() + i);
}
System.out.println("Sum = " + sum);
I invite you to take a look at the testcases I've set up here:
http://ideone.com/Hvbs1
Your code is slow not because you are mixing long
and int
types, but because you are using Long
instead of long
. The Long
type is a proper object, and immutable to boot, so every time you assign a new value to your variable, a new object is being constructed (a possible exception is if a cached object already exists for the new value). This is an expensive operation (relatively speaking).
As you will see from the example code, changing the loop to add a long
instead of an int
does not make it run any faster. The way to speed it up is to change the first variable to a long
instead of a Long
.
Java has no C++ like references. Also, the built-in wrapper classes for primitive types are deliberately made immutable. One of the reasons for this decision is, that the run-time may then cache the wrapper instances for particular values, and avoid having to create a new object (this requires, that you call valueOf
instead of allocating a new object via new
; the compiler does this for boxing).
So, a new object is created every time. Doesn't Java support C++ like feature of returning a reference so that we could've written (possibly): ...
If you use Long
you are explicitly requesting wrapper type from Java. And the convention for wrapper types is: they are immutable. And immutability (as constness in C++) requires that no modifiable internals must be given to the outside. But a C++ like reference would exactly do that. (Let's skip the const reference part because that also wouldn't help you in C++.)
possibly not having to create sum object every time around the loop? Am I right?
Theoretically yes, but if you want that behaviour, why don't you use not a plain long
right from the start?
Others have already explained why Long
takes longer then long and how using
Long.valueOf` may be slightly faster.
Please, don't let this be a reason for not using Long. In all likelihood your overall system throughput time will not be affected by it.
If there are tight loops where this affects performance then use the primitive long
there, a hand-rolled wrapper as Jon describes or MutableLong from apache commons.
精彩评论