字符串实习真的有用吗?

2022-09-02 03:27:51

不久前,我曾就弦乐和各种语言进行过一次对话,弦乐实习的话题出现了。显然,Java和.NET框架会自动使用所有字符串以及几种脚本语言执行此操作。从理论上讲,它可以节省内存,因为您最终不会得到同一字符串的多个副本,并且可以节省时间,因为字符串相等性比较是一个简单的指针比较,而不是通过字符串的每个字符运行O(N)。

但是我越想越怀疑这个概念的好处。在我看来,这些优点主要是理论上的:

  • 首先,要使用自动字符串插入,所有字符串都必须是不可变的,这使得许多字符串处理任务比需要的更难。(是的,我一般都听说过所有关于不变性的论点。这不是重点。
  • 每次创建新字符串时,都必须根据字符串暂存表对其进行检查,这至少是一个 O(N) 操作。(编辑:其中N是字符串的大小,而不是表的大小,因为这会让人感到困惑。因此,除非字符串相等性比较与新字符串创建的比率非常高,否则节省的净时间不太可能是正值。
  • 如果字符串相等性表使用强引用,则当不再需要字符串时,它们将永远不会被垃圾回收,从而浪费内存。另一方面,如果表使用弱引用,则字符串类需要某种终结器来从表中删除字符串,从而减慢了 GC 过程。(这可能非常重要,具体取决于字符串 intern 表的实现方式。最坏的情况是,在某些情况下,从哈希表中删除项目可能需要对整个表进行 O(N) 重建。

这只是我考虑实现细节的结果。我错过了什么吗?在一般情况下,字符串实习实际上是否提供了任何显着的好处?

编辑2:好吧,显然我是在一个错误的前提下运作的。与我交谈的人从未指出,对于新创建的字符串,字符串实习是可选的,实际上给人一种强烈的印象,即事实恰恰相反。感谢乔恩把事情弄清楚了。另一个被接受的答案。


答案 1

不,Java和.NET不会“自动使用所有字符串”执行此操作。他们(好吧,Java和C#)使用以字节码/ IL表示的常量字符串表达式来做到这一点,并通过String.internString.Intern(.NET)方法按需进行。.NET 中的确切情况很有趣,但基本上 C# 编译器将保证对程序集中相等字符串常量的每个引用最终都引用相同的字符串对象。这可以在类型初始化时有效地完成,并且可以节省一堆内存。

它不会在每次创建新字符串时都发生。

(在字符串不变性方面,我非常高兴字符串是不可变的。我不想每次收到参数等时都要复印,非常感谢。我也没有看到它使字符串处理任务变得更加困难...)

正如其他人所指出的那样,在哈希表中查找字符串通常不是O(n)操作,除非您非常不幸地遇到哈希冲突......

就个人而言,我不在用户土地代码中使用字符串实习;如果我想要某种字符串缓存,我会创建一个或类似的东西。这在各种情况下都很有用,在这种情况下,您希望多次遇到相同的字符串(例如.XML元素名称),但是对于简单的集合,您不会污染系统范围的缓存。HashSet<string>


答案 2

首先,要使用自动字符串插入,所有字符串都必须是不可变的,这使得许多字符串处理任务比需要的更难。(是的,我一般都听说过所有关于不变性的论点。这不是重点。

这是真的,字符串在Java中是不可变的。我不确定这是否是一件坏事。在不进入不可变与可变的情况下,我喜欢认为这是一个很棒的设计,因为缓存和更简单,我不会进入。

每次创建新字符串时,都必须根据字符串暂存表对其进行检查,这至少是一个 O(N) 操作。因此,除非字符串相等性比较与新字符串创建的比率非常高,否则节省的净时间不太可能是正值。

不完全是O(n)。您可以执行哈希映射和/或其他数据结构,以使其几乎持续查找。

如果字符串相等性表使用强引用,则当不再需要字符串时,它们将永远不会被垃圾回收,从而浪费内存。另一方面,如果表使用弱引用,则字符串类需要某种终结器来从表中删除字符串,从而减慢了 GC 过程。(这可能非常重要,具体取决于字符串 intern 表的实现方式。最坏的情况是,在某些情况下,从哈希表中删除项目可能需要对整个表进行 O(N) 重建。

你是对的,我同意你的看法。除了我觉得GC处理和微不足道。从长远来看,好处比让垃圾回收器进行额外检查更有用。我不确定你对从哈希表中删除的O(n)是什么意思。哈希表上的大多数操作都是 O(1)

所以总而言之,我认为你假设大多数操作都是线性的。但是查找字符串更接近于恒定时间。因此,这种方法的性能损失可以忽略不计,但内存增加很大。我认为这是值得的。

这里有一个很好的引用,关于实际发生的事情以及它如何节省内存。

为了节省内存(并加快对相等性的测试),Java支持字符串的“实习”。在字符串上调用 intern() 方法时,将对滞留字符串表执行查找。如果表中已存在具有相同内容的 String 对象,则返回对表中 String 的引用。否则,String 将添加到表中,并返回对它的引用。


推荐