扩展java整数缓存

发布于 2024-09-27 15:06:08 字数 337 浏览 6 评论 0原文

由于缓存的原因,一般建议使用 Integer.valueOf(int) 而不是 new Integer(int)

在 JDK 5+ 中,您确实应该使用 valueOf,因为 Integer 现在缓存 -128之间的 Integer 对象>127 并且可以每次都返回相同的 Integer(0) 对象,而不是在全新的相同 Integer 对象上浪费对象构造。

怎样才能扩大范围呢?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

层林尽染 2024-10-04 15:06:08

您可以使用 java.lang.Integer.IntegerCache.high 属性来增加此缓存的大小。
前任 :

java -Djava.lang.Integer.IntegerCache.high=4096 SomeClass.class

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
哎呦我呸! 2024-10-04 15:06:08

我向您提出的问题是:

1)为什么您的代码创建新的 Integer 对象会伤害您?您是否有一个配置文件结果可以分享,以证明创建太多整数会减慢您的速度?一般来说,对象池是一个坏主意。你需要一个好的案例来证明它的合理性。

2)你为什么要做 new Integer(int) ?如果你只是将其保留为原始 int,那么你不仅可以避免“创建新对象”。你根本不会创建任何对象。如果您稍后需要,自动装箱将处理将其转换为整数。

*免责声明我不使用任何一个..我编写性能敏感的代码,但从未达到手动将原始 int 转换为 Integer 的地步。我只是尽可能保留为 int,并在需要时让 JVM 自动装箱。

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.

新一帅帅 2024-10-04 15:06:08

显然,-XX:+AggressiveOpts 将最大值设置为 20000。请参阅 多大的答案是整数缓存吗?

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

无语# 2024-10-04 15:06:08

扩展缓存的范围可能无法满足您的需求,但如果您确实需要缓存更大的范围,则可以使用此代码而不是 Integer.valueOf(int)。您只需将缓存范围值调整到您想要的范围即可。

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);
}

代码来自:http://www.owasp.org/index.php/Java_gotchas

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

長街聽風 2024-10-04 15:06:08

这就是添加整数缓存的原因

[...] 根据语言规范的要求,支持 -128 到 127(含)之间的值的自动装箱的对象标识语义。

如果您分析了您的应用程序并且注意到创建 Integer 对象是一个热点,那么请务必复制整数缓存代码并使用不同的范围编写您自己的代码。否则,你最好把时间花在寻找真正的热点并改进它们上。

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.

拔了角的鹿 2024-10-04 15:06:08

使用 lambda 的 java 8+ 功能和 Map 接口,您可以像这样完成。使用由于关闭而保留的 Map 创建一个独立的缓存。对于创建的每个 newCache,在所有调用 get() 期间都会访问此缓存。

  • 如果低于限制,get(int value) 将返回相同的实例,否则返回新实例。
  • Map.computeIfAbsent() 会将实例放置在地图中(如果该实例不存在)。将返回地图中的值(刚刚添加的或现有的);
@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);

印刷

true
false

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文