Reputation: 151
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?
Upvotes: 4
Views: 4831
Reputation: 40044
Using java 8+ features of lambdas and the Map interface
and you can do it like so. Create an independent cache using a Map
that is preserved due to closure. This cache will be accessed during all invocations of get()
for each newCache
that is created.
get(int value)
will return the same instance if it is under the limit, otherwise, it returns the new instance.@FunctionalInterface
interface IntegerCache {
Integer get(int value);
static IntegerCache newCache(int limit) {
// create a closure of the map and return the method
final Map<Integer, Integer> cache = new HashMap<>();
return value -> {
Integer retVal = Integer.valueOf(value);
if (value < limit) {
return cache.computeIfAbsent(value, v -> Integer.valueOf(v));
}
return retVal;
};
}
}
IntegerCache cache = IntegerCache.newCache(1001);
Integer a = cache.get(1000); // under the limt
Integer b = cache.get(1000);
System.out.println(a == b);
a = cache.get(1002); // over the limit
b = cache.get(1002);
System.out.println(a == b);
prints
true
false
Upvotes: 0
Reputation: 1236
Apparently, the -XX:+AggressiveOpts sets the max to 20000. See the answer on How large is the Integer cache?
Upvotes: 2
Reputation: 7194
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.
Upvotes: 1
Reputation: 1974
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
Upvotes: 14
Reputation: 25139
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
Upvotes: 1
Reputation: 15347
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.
Upvotes: 2