String.intern () в Java 5.0 и 6 использует пространство perm gen, которое обычно имеет небольшой максимальный размер. Это может означать, что вам не хватает места, даже если есть много свободной кучи.
Java 7 использует свою обычную кучу для хранения строк intern () ed.
Сравнение строк это довольно быстро, и я не думаю, что есть много преимуществ в сокращении времени сравнения, если учесть накладные расходы.
Другая причина, по которой это может быть сделано, - это если много повторяющихся строк. Если дублирования достаточно, это может сэкономить много памяти.
Более простой способ кэширования строк - использовать кэш LRU, такой как LinkedHashMap
private static final int MAX_SIZE = 10000;
private static final Map<String, String> STRING_CACHE = new LinkedHashMap<String, String>(MAX_SIZE*10/7, 0.70f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
return size() > 10000;
}
};
public static String intern(String s) {
// s2 is a String equals to s, or null if its not there.
String s2 = STRING_CACHE.get(s);
if (s2 == null) {
// put the string in the map if its not there already.
s2 = s;
STRING_CACHE.put(s2,s2);
}
return s2;
}
Вот пример того, как это работает.
public static void main(String... args) {
String lo = "lo";
for (int i = 0; i < 10; i++) {
String a = "hel" + lo + " " + (i & 1);
String b = intern(a);
System.out.println("String \"" + a + "\" has an id of "
+ Integer.toHexString(System.identityHashCode(a))
+ " after interning is has an id of "
+ Integer.toHexString(System.identityHashCode(b))
);
}
System.out.println("The cache contains "+STRING_CACHE);
}
печать
String "hello 0" has an id of 237360be after interning is has an id of 237360be
String "hello 1" has an id of 5736ab79 after interning is has an id of 5736ab79
String "hello 0" has an id of 38b72ce1 after interning is has an id of 237360be
String "hello 1" has an id of 64a06824 after interning is has an id of 5736ab79
String "hello 0" has an id of 115d533d after interning is has an id of 237360be
String "hello 1" has an id of 603d2b3 after interning is has an id of 5736ab79
String "hello 0" has an id of 64fde8da after interning is has an id of 237360be
String "hello 1" has an id of 59c27402 after interning is has an id of 5736ab79
String "hello 0" has an id of 6d4e5d57 after interning is has an id of 237360be
String "hello 1" has an id of 2a36bb87 after interning is has an id of 5736ab79
The cache contains {hello 0=hello 0, hello 1=hello 1}
Это обеспечит ограничение числа кэшей intern () ed Strings.
Более быстрый, но менее эффективный способ - использовать фиксированный массив.
private static final int MAX_SIZE = 10191;
private static final String[] STRING_CACHE = new String[MAX_SIZE];
public static String intern(String s) {
int hash = (s.hashCode() & 0x7FFFFFFF) % MAX_SIZE;
String s2 = STRING_CACHE[hash];
if (!s.equals(s2))
STRING_CACHE[hash] = s2 = s;
return s2;
}
Тест выше работает так же, за исключением того, что вам нужно
System.out.println("The cache contains "+ new HashSet<String>(Arrays.asList(STRING_CACHE)));
для распечатки содержимого, которое показывает следующее, включите в null
пустые записи.
The cache contains [null, hello 1, hello 0]
Преимуществом этого подхода является скорость и то, что он может безопасно использоваться многопоточностью без блокировки. то есть не имеет значения, имеют ли разные потоки различное представление о STRING_CACHE.