4

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?

Vladimir Vagaytsev
  • 2,871
  • 9
  • 33
  • 36
Trustin
  • 151
  • 1
  • 4

6 Answers6

14

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
Daniel Teply
  • 1,974
  • 1
  • 13
  • 10
2

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

Community
  • 1
  • 1
cpurdy
  • 1,177
  • 5
  • 12
2

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.

bwawok
  • 14,898
  • 7
  • 32
  • 43
  • 1
    Although you don't specifically answer the OP's question, I 100% agree with you here. Pooling such "cheap" Objects is almost certainly a bad idea. – Waldheinz Oct 14 '10 at 14:55
1

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

Alan Geleynse
  • 24,821
  • 5
  • 46
  • 55
1

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.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Dan Berindei
  • 7,054
  • 3
  • 41
  • 48
0

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.
  • Map.computeIfAbsent() will place the instance in the map if it is not there. The value that is in the map (just added or existing) will be returned;
@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
WJS
  • 36,363
  • 4
  • 24
  • 39