使用 java.lang.String.intern() 是好习惯吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1091045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it good practice to use java.lang.String.intern()?
提问by Daniel Rikowski
The Javadoc about String.intern()
doesn't give much detail. (In a nutshell: It returns a canonical representation of the string, allowing interned strings to be compared using ==
)
Javadoc aboutString.intern()
没有提供太多细节。(简而言之:它返回字符串的规范表示,允许使用 比较内部字符串==
)
- When would I use this function in favor to
String.equals()
? - Are there side effects not mentioned in the Javadoc, i.e. more or less optimization by the JIT compiler?
- Are there further uses of
String.intern()
?
- 我什么时候会使用这个功能来支持
String.equals()
? - Javadoc 中是否有没有提到的副作用,即 JIT 编译器或多或少的优化?
- 有没有进一步的用途
String.intern()
?
采纳答案by dfa
When would I use this function in favor to String.equals()
我什么时候会使用这个函数来支持 String.equals()
when you need speedsince you can compare strings by reference (== is faster than equals)
当您需要速度时,因为您可以通过引用比较字符串(== 比等于快)
Are there side effects not mentioned in the Javadoc?
Javadoc 中有没有提到的副作用?
The primary disadvantage is that you have to remember to make sure that you actually do intern() all of the strings that you're going to compare. It's easy to forget to intern() all strings and then you can get confusingly incorrect results. Also, for everyone's sake, please be sure to very clearly document that you're relying on the strings being internalized.
主要的缺点是您必须记住确保您确实执行了要比较的所有字符串的 intern() 。很容易忘记对所有字符串进行 intern() ,然后您可能会得到令人困惑的错误结果。此外,为大家着想,请务必非常清楚地记录您所依赖的字符串被内化。
The second disadvantage if you decide to internalize strings is that the intern() method is relatively expensive. It has to manage the pool of unique strings so it does a fair bit of work (even if the string has already been internalized). So, be careful in your code design so that you e.g., intern() all appropriate strings on input so you don't have to worry about it anymore.
如果您决定内部化字符串,第二个缺点是 intern() 方法相对昂贵。它必须管理唯一字符串池,因此它会做一些工作(即使字符串已经被内部化)。所以,在你的代码设计中要小心,这样你就可以在输入时使用 intern() 所有合适的字符串,这样你就不必再担心了。
(from JGuru)
(来自JGuru)
Third disadvantage (Java 7 or less only): interned Strings live in PermGen space, which is usually quite small; you may run into an OutOfMemoryError with plenty of free heap space.
第三个缺点(仅限 Java 7 或更低版本):实习字符串存在于 PermGen 空间中,该空间通常非常小;您可能会遇到 OutOfMemoryError 并且有足够的空闲堆空间。
(from Michael Borgwardt)
(来自迈克尔·博格沃特)
回答by objects
Am not aware of any advantages, and if there were in one would think that equals() would itself use intern() internally (which it doesn't).
我不知道有什么优点,如果有的话会认为 equals() 本身会在内部使用 intern() (它没有)。
回答by Daniel Brückner
This has (almost) nothing to do with string comparison. String interningis intended for saving memory if you have many strings with the same content in you application. By using String.intern()
the application will only have one instance in the long run and a side effect is that you can perform fast reference equality comparison instead of ordinary string comparison (but this is usually not advisable because it is realy easy to break by forgetting to intern only a single instance).
这(几乎)与字符串比较无关。如果您的应用程序中有许多具有相同内容的字符串,则字符串实习旨在节省内存。从String.intern()
长远来看,使用该应用程序只会有一个实例,副作用是您可以执行快速引用相等比较而不是普通的字符串比较(但这通常是不可取的,因为忘记实习真的很容易破坏)单个实例)。
回答by Mikko Maunu
I would examine intern and ==-comparison instead of equals only in the case of equals-comparison being bottleneck in multiple comparisons of string. This is highly unlikely to help with small number of comparisons, because intern() is not free. After aggressively interning strings you will find calls to intern() getting slower and slower.
只有在 equals-comparison 成为字符串多重比较中的瓶颈的情况下,我才会检查 intern 和 ==-comparison 而不是 equals。这对少量比较不太可能有帮助,因为 intern() 不是免费的。在积极地实习字符串之后,您会发现对 intern() 的调用越来越慢。
回答by Pete Kirkham
When would I use this function in favor to String.equals()
我什么时候会使用这个函数来支持 String.equals()
Given they do different things, probably never.
鉴于他们做不同的事情,可能永远不会。
Interning strings for performance reasons so that you can compare them for reference equality is only going to be of benefit if you are holding references to the strings for a while - strings coming from user input or IO won't be interned.
出于性能原因对字符串进行实习,以便您可以比较它们的引用相等性,这只会在您暂时持有对字符串的引用时有益 - 来自用户输入或 IO 的字符串不会被实习。
That means in your application you receive input from an external source and process it into an object which has a semantic value - an identifier say - but that object has a type indistinguishable from the raw data, and has different rules as to how the programmer should use it.
这意味着在您的应用程序中,您从外部源接收输入并将其处理为具有语义值的对象 - 一个标识符说 - 但该对象具有与原始数据无法区分的类型,并且对于程序员应该如何处理有不同的规则用它。
It's almost always better to create a UserId
type which is interned ( it's easy to create a thread-safe generic interning mechanism ) and acts like an open enum, than to overload the java.lang.String
type with reference semantics if it happens to be a User ID.
创建一个内部UserId
类型(创建一个线程安全的通用内部机制很容易)并且像一个开放的枚举一样工作,比java.lang.String
使用引用语义重载类型(如果它恰好是一个用户 ID)要好得多。
That way you don't get confusion between whether or not a particular String has been interned, and you can encapsulate any additional behaviour you require in the open enum.
这样您就不会在是否已实习特定字符串之间产生混淆,并且您可以在开放枚举中封装您需要的任何其他行为。
回答by wm_eddie
I would vote for it not being worth the maintenance hassle.
我会投票支持它不值得维护麻烦。
Most of the time, there will be no need, and no performance benefit, unless you're code does a lot of work with substrings. In which case the String class will use the original string plus an offset to save memory. If your code uses substrings a lot, then I suspect that it'll just cause your memory requirements to explode.
大多数情况下,没有必要,也没有性能优势,除非您的代码对子字符串进行了大量工作。在这种情况下,String 类将使用原始字符串加上一个偏移量来节省内存。如果您的代码大量使用子字符串,那么我怀疑它只会导致您的内存需求激增。
回答by Gili Nachum
String.intern()
is definitely garbage collected in modern JVMs.
The following NEVER runs out of memory, because of GC activity:
String.intern()
绝对是现代 JVM 中的垃圾收集。
由于 GC 活动,以下内容永远不会耗尽内存:
// java -cp . -Xmx128m UserOfIntern
public class UserOfIntern {
public static void main(String[] args) {
Random random = new Random();
System.out.println(random.nextLong());
while (true) {
String s = String.valueOf(random.nextLong());
s = s.intern();
}
}
}
See more (from me) on the myth of non GCed String.intern().
查看更多(来自我)关于非 GCed String.intern()的神话。
回答by asaf
The real reason to use intern is not the above. You get to use it after you get out-of-memory error. Lots of the string in a typical program are String.substring() of other big string [think of taking out a user-name from a 100K xml file. The java implementation is that , the substring holds a reference to the original string and the start+end in that huge string. (The thought behind it is a reuse of the same big string)
使用实习生的真正原因并非上述原因。您可以在出现内存不足错误后使用它。典型程序中的很多字符串是其他大字符串的 String.substring() [想想从 100K xml 文件中取出用户名。Java 实现是,子字符串包含对原始字符串和该巨大字符串中的 start+end 的引用。(背后的想法是对同一个大字符串的重用)
After 1000 big files , from which you only save 1000 short names , you will keep in memory the whole 1000 files! Solution: in this scenario just use smallsubstring.intern()
在 1000 个大文件之后,您只保存 1000 个短名称,您将把整个 1000 个文件保存在内存中!解决方案:在这种情况下只需使用 smallsubstring.intern()
回答by Paul Taylor
I am using intern to save memory, I hold a large amount of String data in memory and moving to use intern() saved a massive amount of memory. Unfortunately although it use alot less memory the memory it does use is stored in PermGen memory not Heap and it is difficult to explain to customers how to increase the allocation of this type of memory.
我正在使用实习生来节省内存,我在内存中保存了大量的字符串数据,并转而使用实习生()节省了大量内存。不幸的是,虽然它使用的内存很少,但它使用的内存存储在 PermGen 内存中而不是 Heap 中,并且很难向客户解释如何增加这种类型的内存的分配。
So is there an alternative to intern() for reducing memory consumption, (the == versus equals performance benefits is not a aissue for me)
那么有没有替代 intern() 来减少内存消耗的方法,( == 与 equals 性能优势对我来说不是问题)
回答by aleroot
Comparing strings with == is much faster than with equals()
用 == 比较字符串比用 equals() 快得多
5 Time faster, but since String comparision usually represents only a small percentage of the total execution time of an application, the overall gain is much smaller than that, and the final gain will be diluted to a few percent.
5 时间更快,但由于字符串比较通常只占应用程序总执行时间的一小部分,因此整体收益要小得多,最终收益会被稀释到几个百分点。
String.intern() pull the string away from Heap and put it in PermGen
String.intern() 将字符串从 Heap 中拉出并放入 PermGen
String internalized are put in a different storage area : Permanent Generationwhich is an area of the JVM that is reserved for non-user objects, like Classes, Methods and other internal JVM objects. The size of this area is limited and the is much precious than heap. Being this area smaller than Heap there are more probability to use all the space and get an OutOfMemoryException.
内部化的字符串放在不同的存储区域:永久代,这是 JVM 的一个区域,为非用户对象保留,如类、方法和其他内部 JVM 对象。这个区域的大小是有限的,而且比堆宝贵得多。由于该区域小于 Heap,因此更有可能使用所有空间并获得 OutOfMemoryException。
String.intern() string are garbage collected
String.intern() 字符串被垃圾收集
In the new versions of JVM also internalized string are garbage collected when not referenced by any object.
在新版本的 JVM 中,当没有任何对象引用时,内部化的字符串也会被垃圾收集。
Keeping in mind the above 3 point you could deduct that String intern() could be useful only in few situation when you do a lot of string comparison, however it is better don't use internal string if you don't know exactly what you are doing ...
牢记以上 3 点,您可以推断出 String intern() 仅在进行大量字符串比较的少数情况下才有用,但是如果您不确切地知道自己是什么,最好不要使用内部字符串是做 ...