Java字符串实习的替代方案

Java字符串实习的替代方案,java,string,memory,string-interning,Java,String,Memory,String Interning,由于Java的默认字符串实习受到了很多负面影响,我正在寻找一种替代方法 你能推荐一个API,它是Java字符串实习的一个很好的替代方案吗?我的应用程序使用Java6。我的要求主要是通过实习避免重复字符串 关于坏消息: String intern是通过本机方法实现的。而C实现使用了大约1k条目的固定大小,对大量字符串的伸缩性非常差 Java 6在Perm gen中存储了内部字符串,因此不是GC的,可能会导致Perm gen错误。我知道这在Java7中是固定的,但我不能升级到Java7 为什么我

由于Java的默认字符串实习受到了很多负面影响,我正在寻找一种替代方法

你能推荐一个API,它是Java字符串实习的一个很好的替代方案吗?我的应用程序使用Java6。我的要求主要是通过实习避免重复字符串

关于坏消息:
  • String intern是通过本机方法实现的。而C实现使用了大约1k条目的固定大小,对大量字符串的伸缩性非常差
  • Java 6在Perm gen中存储了内部字符串,因此不是GC的,可能会导致Perm gen错误。我知道这在Java7中是固定的,但我不能升级到Java7
为什么我需要使用intering?
  • 我的应用程序是一个服务器应用程序,堆大小为10-20G,用于不同的部署
  • 在分析过程中,我们发现成百上千的字符串是重复的,我们可以通过避免存储重复字符串来显著提高内存使用率
  • 内存一直是我们的瓶颈,因此我们针对它而不是做任何过早的优化
String intern是通过本机方法实现的。而C实现使用了大约1k条目的固定大小,对大量字符串的伸缩性非常差

它对几千根弦的伸缩性很差

Java 6在Perm gen.中存储内部字符串,因此不是GC'd

当烫发机被清理时,它会被清理掉,这并不常见,但如果你不增加它,这意味着你可以达到这个空间的最大值

我的应用程序是一个服务器应用程序,堆大小为10-20G,用于不同的部署

我建议你考虑使用堆内存。在一个应用程序中,我有500 GB的堆外内存和大约1 GB的堆内内存。它并非在所有情况下都有用,但值得考虑

在分析过程中,我们发现成百上千的字符串是重复的,我们可以通过避免存储重复字符串来显著提高内存使用率

为此,我使用了一个简单的字符串数组。这是非常轻的重量,您可以控制字符串的上限存储容易


下面是一个通用interner的示例

class Interner<T> {
    private final T[] cache;

    @SuppressWarnings("unchecked")
    public Interner(int primeSize) {
        cache = (T[]) new Object[primeSize];
    }

    public T intern(T t) {
        int hash = Math.abs(t.hashCode() % cache.length);
        T t2 = cache[hash];
        if (t2 != null && t.equals(t2))
            return t2;
        cache[hash] = t;
        return t;
    }
}
class实习生{
私有最终T[]缓存;
@抑制警告(“未选中”)
公共实习生(国际顶级){
cache=(T[])新对象[primeSize];
}
公共技术实习生(T){
int hash=Math.abs(t.hashCode()%cache.length);
t2=缓存[散列];
如果(t2!=null&&t.equals(t2))
返回t2;
cache[hash]=t;
返回t;
}
}
这个缓存的一个有趣的特性是它不是线程安全的并不重要


为了获得更高的速度,您可以使用2倍大小的幂和位掩码,但它更复杂,并且可能无法很好地工作,这取决于哈希代码的计算方式。

我的一部分尊重您发布的要求,但如果“坏消息”足以让您避免这些要求,那么我真的必须询问您是如何分析您的应用程序的(如果有的话)确定Java字符串不合适。您是否注意到应用程序中有关这些问题的问题?如果没有,我就不用担心了。@Keppil我的应用程序有数十万个重复字符串。所以实习对我来说是必须的。@pst希望我已经回答了你的问题。我想你指的是地图而不是集合。我需要一些线程安全的东西,一旦字符串不再被引用,就会对它们进行GC。类似于并发弱散列映射。@ManojGumber(impl with map)(提到Guava Interner)对于字符串数组方法,它只是一个无序的集合吗?@peter Lawrey它将如何处理冲突。i、 e.当两个具有不同哈希代码的字符串指向同一缓存索引时?是否有一种假设,即您使Interner的大小与您期望的不同字符串的数量相同?如果发生冲突,它将替换其中的值。这个大小需要比你认为最佳的字符串数大2-3倍,因为它不想处理冲突。顺便说一句,偶数HashMap将是条目数的1.4到2.8倍。您可以使用查找任何大小的“有趣”素数。