Java 在 for-each 循环中实习字符串
Does Java intern Strings in a for-each loop
我读过有关 SO 的问题,解释说 Java 会自动实习字符串文字,并且显然会在调用 intern()
时实习。但是,我想知道是否在一个循环中(在我的例子中是 foreach
循环)字符串是否也被自动保留。我问是因为我正在实习字符串以在几个非常大的 LinkedHashMaps
中节省内存,并且想知道调用 intern()
是否多余。
示例:
String array[] = createLargeArbitraryArray();
Map<String, Float> map = new LinkedHashMap<String, Float>(array.length);
for (String s : array)
map.put(s, 1f);
}
下一个示例在内存使用方面是否会与第一个(假设相同 array
值)有任何差异,或者 s
是否已经在该点实习?
String array[] = createLargeArbitraryArray();
Map<String, Float> map = new LinkedHashMap<String, Float>(array.length);
for (String s : array)
map.put(s.intern(), 1f);
}
我意识到在这种情况下,可能没有等效的字符串,但在我的情况下,我有几个映射的自定义键,这些映射最终确实使用了重复的字符串值,我想知道是否调用 intern()
在这一点上节省内存是多余的还是多余的。
要补充这个问题,如果数组是从文字创建的(在这种情况下,它们最初是驻留的),然后作为参数传递给方法,上面的循环是否会使用驻留字符串?即:
/**
* @param array created from literals
*/
public void populateMap(String[] array) {
for (String s : array)
map.put(s, 1f); // Interned or not?
}
在这种情况下,要么 s
被驻留,因为 array
一开始就被驻留,要么 s
没有被驻留,因为它在循环参数中被声明为新对象.哪个是正确的?
编辑:为了进一步解释我实习的原因,我想释放堆中的内存以避免达到最大堆大小或 GC 开销限制。在这种情况下,性能和速度对我来说并不是极其重要。
在这里明确调用 intern()
是正确的方法(或者像 PC luddite 所说的,检查你是否真的需要 interning)。我不知道 JVM 中有任何 JIT 编译器可以做到这一点(即使有一些优化可以做到这一点,您也不应该依赖它)。
如果数组是从驻留字符串创建的,然后传递给方法然后使用,那么将使用 "interned" 字符串。不会创建额外的字符串。
我读过有关 SO 的问题,解释说 Java 会自动实习字符串文字,并且显然会在调用 intern()
时实习。但是,我想知道是否在一个循环中(在我的例子中是 foreach
循环)字符串是否也被自动保留。我问是因为我正在实习字符串以在几个非常大的 LinkedHashMaps
中节省内存,并且想知道调用 intern()
是否多余。
示例:
String array[] = createLargeArbitraryArray();
Map<String, Float> map = new LinkedHashMap<String, Float>(array.length);
for (String s : array)
map.put(s, 1f);
}
下一个示例在内存使用方面是否会与第一个(假设相同 array
值)有任何差异,或者 s
是否已经在该点实习?
String array[] = createLargeArbitraryArray();
Map<String, Float> map = new LinkedHashMap<String, Float>(array.length);
for (String s : array)
map.put(s.intern(), 1f);
}
我意识到在这种情况下,可能没有等效的字符串,但在我的情况下,我有几个映射的自定义键,这些映射最终确实使用了重复的字符串值,我想知道是否调用 intern()
在这一点上节省内存是多余的还是多余的。
要补充这个问题,如果数组是从文字创建的(在这种情况下,它们最初是驻留的),然后作为参数传递给方法,上面的循环是否会使用驻留字符串?即:
/**
* @param array created from literals
*/
public void populateMap(String[] array) {
for (String s : array)
map.put(s, 1f); // Interned or not?
}
在这种情况下,要么 s
被驻留,因为 array
一开始就被驻留,要么 s
没有被驻留,因为它在循环参数中被声明为新对象.哪个是正确的?
编辑:为了进一步解释我实习的原因,我想释放堆中的内存以避免达到最大堆大小或 GC 开销限制。在这种情况下,性能和速度对我来说并不是极其重要。
在这里明确调用 intern()
是正确的方法(或者像 PC luddite 所说的,检查你是否真的需要 interning)。我不知道 JVM 中有任何 JIT 编译器可以做到这一点(即使有一些优化可以做到这一点,您也不应该依赖它)。
如果数组是从驻留字符串创建的,然后传递给方法然后使用,那么将使用 "interned" 字符串。不会创建额外的字符串。