Extending java Integer cache - java

There's a general advice to use Integer.valueOf(int) instead of new Integer(int) because of caching.
In JDK 5+, you should really use valueOf because Integer now caches Integer objects between -128 and 127 and can hand you back the same exact Integer(0) object every time instead of wasting an object construction on a brand new identical Integer object.
How can extend the range?

You can use the java.lang.Integer.IntegerCache.high property to increase the size of this cache.
ex :
java -Djava.lang.Integer.IntegerCache.high=4096 SomeClass.class

My questions to you are:
1) Why is your code making new Integer objects hurting you? Do you have a profile result to share, to prove that making too many Integers is slowing your down? Object pooling, in general, is a BAD idea. You need a good case to justify it.
2) Why are you doing new Integer(int)? If you just keep it as a primitive int, not only will you avoid "creating a new object". you will not create any object at all. Auto boxing will handle converting it to an Integer if you need it at a later point in time.
*Disclaimer I Don't use EITHER.. I write performance sensitive code, but have never come to a point where I would manually turn a primitive int into an Integer. I just keep as an int whenever possible, and let the JVM autobox if it is needed.

Apparently, the -XX:+AggressiveOpts sets the max to 20000. See the answer on How large is the Integer cache?

Extending the range of the cache may not get you what you are wanting, but if you have a real need to cache a greater range, you can use this code instead of Integer.valueOf(int). You just need to adjust the cache range values to the range you want.
private static class IntegerCache
{
private IntegerCache(){}
static final Integer cache[] = new Integer[-(-128) + 127 + 1];
static
{
for(int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
}
public static Integer valueOf(int i)
{
final int offset = 128;
if (i >= -128 && i <= 127) // must cache
{
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
The code is from: http://www.owasp.org/index.php/Java_gotchas

This is why the integer cache was added:
[...] to support the object identity semantics of autoboxing for values between -128 and 127 (inclusive), as required by the language specification.
If you profiled your app and you noticed that creating Integer objects is a hotspot, then by all means, copy the integer cache code and write your own with a different range. Otherwise your time would be better spent finding the real hotspots and improving those.

Related

Integer caching in Java with new operator

In the below class I have tried to compare the wrapper class with the primitive but the results are different.
I have checked the following links links:
The more interesting question is why new Object(); should be required to create a unique instance every time? i. e. why is new Object(); not allowed to cache? The answer is the wait(...) and notify(...) calls. Caching new Object()s would incorrectly cause threads to synchronize with each other when they shouldn't.
If there is a new object then how are a and c equal?
If b is equal to c and c is equal to a, then a should be equal to b. But in following case I got a != c.
Please explain.
class WrapperCompare {
public static void main (String args[]) {
Integer a = new Integer(10);
Integer b = 10;
int c=10;
System.out.println(b==c); //true
System.out.println(a==b); //false
System.out.println(a==c); //true
}
}
Update:
By referring to this link Integer caching.
Basically, the Integer class keeps a cache of Integer instances in the range of -128 to 127, and all autoboxing, literals and uses of Integer.valueOf() will return instances from that cache for the range it covers.
So in this case all statements should be true.
Explanation
When you compare Integer vs int with ==, it needs to convert the Integer to an int. This is called unboxing.
See JLS§5.1.8:
If r is a reference of type Integer, then unboxing conversion converts r into r.intValue()
At that point, you are comparing int vs int. And primitives have no notion of instances, they all refer to the same value. As such, the result is true.
So the actual code you have is
a.intValue() == c
leading to a comparison of 10 == 10, both int values, no Integer instances anymore.
You can see that new Integer(...) indeed creates new instances, when you compare Integer vs Integer. You did that in a == b.
Note
The constructor new Integer(...) is deprecated. You should instead use Integer#valueOf, it is potentially faster and also uses an internal cache. From the documentation:
Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
The caching is important to note here, since it yields to == being true again (for cached values):
Integer first = Integer.valueOf(10);
Integer second = Integer.valueOf(10);
System.out.println(first == second); // true
The caching is guaranteed for values between -128 and +127, but may also be used for others.
Also note that your b actually comes out of the cache, since
Integer b = 10;
// same as
Integer b = Integer.valueOf(10);
// and not
Integer b = new Integer(10);
So boxing goes through Integers cache (see JLS§5.1.7).

Java Autoboxing through a method

Let's say that I have a class:
class A {
private Integer i;
public int getI() {
return i;
}
// Setter, etc.
}
and I write:
A a = // initializer
Integer b = a.getI();
how many Integers will there be? My naive reading about autoboxing/unboxing leads me to believe that the answer is 2, but if getI() were:
public Integer getI();
then the answer would be 1.
You are absolutely correct, with one caveat: the answer to the first part depends on the value of Integer i.
In the first scenario, one Integer is created in the constructor, and the other one is created when boxing the int coming from getI()
In the second scenario, there needs to be no boxing, so there's only one Integer object.
Note: if the value of the Integer i is small (more precisely, between -128 and 127, inclusive), autoboxing will produce the same Integer through interning.
Correct....ish
It's theoretically possible the Compiler/JIT/JVM/etc could optimise out the autoboxing but I've no idea if it actually would.
It's also possible the same Integer object would be re-used. For example Integer.valueOf(2) is guaranteed to give you the same Integer object every time you call it and re-use the same object. This is only guaranteed for values in the range -128 to +127 inclusive though, it may happen outside that range but should not be relied upon.

different output for same code in Java

I am new to java. I know somewhat about the wrapper classes and primitive datatypes, but what I have come across is surprising. On changing the values of the variables i and j from 1000 to 100, the output changes from false to true. I need to know the mechanism behind this.
class Demo{
public static void main(String[] args){
Integer i=1000,j=1000;
if(i==j)
System.out.println("true");
else
System.out.println("false");
}
}
the above code gives me "false" while..
class Demo{
public static void main(String[] args){
Integer i=100,j=100;
if(i==j)
System.out.println("true");
else
System.out.println("false");
}
}
the above code give me "true"
Caching in Wrapper Classes
Integer has internal cache for values ranging from -128 to 127.
So for numbers within this range, the same instance of Integer is returned. == compares by instance, and so the same instance is used for 100.
Source JDK 1.6:
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
return IntegerCache.cache[i + offset];
}
return new Integer(i);
}
Caching in wrapper classes Java
Purpose of Caching
The purpose is mainly to save memory, which also leads to faster code due to better cache efficiency.
Use .equals when comparing value, not identity
If you are comparing two Integers, you should use i.equals(j) just like you would do to correctly compare the value of Strings. Also keep in mind that any operation which will unbox an Integer places an implicit call to Integer.intValue(), so remember to make these calls carefully, knowing when your Integer might be null.
To compare the contents of objects (instead of their identity) use equals instead of ==. This will give consistent results.
Wrapper class Integer has internal cache for -127 to 127. So when you assign same values which are within this range same instance will be returned. For 1000 two different 'new'ed instances are returned giving false on == comparision.
If you use int instead of Integer, results will not be surprising. For consistent result with your approach, use equals() method instead of ==.

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;
System.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 usingLong.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.

Increment a Integer's int value?

How do I increment a Integer's value in Java? I know I can get the value with intValue, and I can set it with new Integer(int i).
playerID.intValue()++;
does not seem to work.
Note: PlayerID is a Integer that has been created with:
Integer playerID = new Integer(1);
Integer objects are immutable, so you cannot modify the value once they have been created. You will need to create a new Integer and replace the existing one.
playerID = new Integer(playerID.intValue() + 1);
As Grodriguez says, Integer objects are immutable. The problem here is that you're trying to increment the int value of the player ID rather than the ID itself. In Java 5+, you can just write playerID++.
As a side note, never ever call Integer's constructor. Take advantage of autoboxing by just assigning ints to Integers directly, like Integer foo = 5. This will use Integer.valueOf(int) transparently, which is superior to the constructor because it doesn't always have to create a new object.
Java 7 and 8. Increment DOES change the reference, so it references to another Integer object. Look:
#Test
public void incInteger()
{
Integer i = 5;
Integer iOrig = i;
++i; // Same as i = i + 1;
Assert.assertEquals(6, i.intValue());
Assert.assertNotEquals(iOrig, i);
}
Integer by itself is still immutable.
AtomicInteger
Maybe this is of some worth also: there is a Java class called AtomicInteger.
This class has some useful methods like addAndGet(int delta) or incrementAndGet() (and their counterparts) which allow you to increment/decrement the value of the same instance. Though the class is designed to be used in the context of concurrency, it's also quite useful in other scenarios and probably fits your need.
final AtomicInteger count = new AtomicInteger( 0 ) ;
…
count.incrementAndGet(); // Ignoring the return value.
Integer objects are immutable. You can't change the value of the integer held by the object itself, but you can just create a new Integer object to hold the result:
Integer start = new Integer(5);
Integer end = start + 5; // end == 10;
For Java 7, increment operator '++' works on Integers. Below is a tested example
Integer i = new Integer( 12 );
System.out.println(i); //12
i = i++;
System.out.println(i); //13
Maybe you can try:
final AtomicInteger i = new AtomicInteger(0);
i.set(1);
i.get();
You can use IntHolder as mutable alternative to Integer. But does it worth?
All the primitive wrapper objects are immutable.
I'm maybe late to the question but I want to add and clarify that when you do playerID++, what really happens is something like this:
playerID = Integer.valueOf( playerID.intValue() + 1);
Integer.valueOf(int) will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
After Java 8, we can use as below
import java.lang.Math;
Math.incrementExact(playerID);
//it increment the integer value to + 1. It is also available for long

Categories