当前位置: 首页 > 面试题库 >

字符串实习真的有用吗?

何承
2023-03-14
问题内容

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

但是,我考虑得越多,对这个概念的好处就越持怀疑态度。在我看来,优点主要是理论上的:

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

这只是我考虑实施细节的结果。有什么我想念的吗?在一般情况下,字符串实习实际上能提供任何重大好处吗?

编辑2:
好的,显然我是在错误的前提下操作的。我与之交谈的人从来没有指出过字符串插入对于新创建的字符串是可选的,实际上给人的强烈印象是相反的说法是正确的。感谢乔恩解决问题。另一个为他接受的答案。


问题答案:

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

不会 发生在每次创建一个新的字符串的时间。

(在字符串不变性方面,我 非常
高兴字符串是不变的。我不想每次收到参数等时都必须复制一个副本,非常感谢。我还没有看到它使字符串成为字符串。要么更困难地处理任务…)

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

我个人不使用字符串形式的用户域代码。如果我想要某种形式的字符串缓存,我将创建一个HashSet<string>或类似的名称。这在各种情况下很有用,因为您希望多次遇到相同的字符串(例如XML元素名称),但是通过简单的收集就不会污染系统范围的缓存。



 类似资料:
  • 问题内容: 管这个问题在实际中没有任何实际用途,但我对Python如何进行字符串实习感到好奇。我注意到以下内容。 这是我所期望的。 您也可以这样做。 那真是太聪明了! 但是你不能这样做。 Python为什么不评估,并意识到它s1与指向相同的地址相同?最后一个块到底在做什么False呢? 问题答案: 这是特定于实现的,但是你的解释器可能是内部编译时常量,而不是运行时表达式的结果。 接下来,我使用CP

  • 问题内容: 常见的JavaScript引擎(例如V8和WebKit的JavaScriptCore)是否对JavaScript字符串使用字符串插入?还是它们实际上在内存中保留了多个相同字符串的实例? 问题答案: 是。通常,会插入JS源中的任何文字字符串,标识符或其他常量字符串。但是,实施细节(例如,确切地说是被实习者)以及实习发生的时间都不同。 请注意,尽管字符串值与字符串对象不同,但字符串对象没有

  • 问题内容: 为什么Python仅内置字符串?应该可以扩展到可哈希和可比较的类,对吗? 问题答案: 内联事物的目的是能够通过比较它们的内存地址来进行比较。您要确保永远不要创建两个具有相同值的对象(当程序请求创建一个与现有对象具有相同值的第二个对象时,它会收到对先前存在的对象的引用)。这要求你要实习的东西是 不变的 ; 如果一个被拘禁对象的值可以改变,那么按地址比较它们是行不通的。 在Python中,

  • 布尔值必须为True或False。 那为什么 输出:是 我不明白为什么是打印,因为“poi”不是真是假。

  • 来自String类的intern方法的javaDocs: 调用intern方法时,如果池中已经包含一个由equals(Object)方法确定的等于此String对象的字符串,则返回池中的字符串。否则,将此String对象添加到池中并返回对此String对象的引用。 考虑以下用例: 有人能解释为什么为真而以下为假吗: <代码>系统。出来println(fifth==第五个.intern()) <代码

  • 问题内容: 我们都知道这String在Java 中是不可变的,但是请检查以下代码: 为什么该程序会这样运行?为何值和改变了,但没有改变? 问题答案: 是不可变的*,但这仅意味着你无法使用其公共API对其进行更改。 你在这里所做的是使用反射来绕过常规API。同样,你可以更改枚举的值,更改整数自动装箱中使用的查找表等。 现在,原因s1和s2变化值是它们都引用相同的实习字符串。编译器执行此操作(如其他答