问题标签 [string-interning]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
python - 什么决定了哪些字符串在什么时候被保留?
应该s1 is s2
给出多少个字符False
?极限在哪里?即我在问一个字符串在python开始制作它的单独副本之前需要多长时间。
java - 我不应该在 Java 中执行 `String s = new String("a new string");`,即使使用自动字符串实习?
好的,这个问题是这个问题的延伸
Java 字符串:"String s = new String("silly");"
上面的问题和这个问题问的一样,但我有一个新的怀疑点。
根据Effective Java
上述问题的答案,我们不应该这样做String s = new String("a new string");
,因为那会创建不必要的对象。
我不确定这个结论,因为我认为 Java 正在做自动字符串实习,这意味着对于一个字符串,无论如何内存中只有一个副本。
那么让我们看看String s = new String("a new string");
。
"a new string"
已经是在内存中创建的字符串。
当我这样做时String s = new String("a new string");
,那s
是也"a new string"
。所以根据automatic string interning
,s
应该是指向 的同一个内存地址"a new string"
吧?
那么我们怎么能说我们创造了不必要的对象呢?
.net - 任何弱实习集合(对于不可变对象)
在某些涉及不可变对象的情况下,可能会出现许多语义相同的不同对象。一个简单的例子是将文件中的多行文本读入字符串。从程序的角度来看,两行具有相同的字符序列这一事实是“巧合”,但从程序员的角度来看,可能会出现大量重复。如果许多字符串实例是相同的,则将对这些不同实例的引用更改为对单个实例的引用将节省内存,并且还有助于它们之间的比较(如果两个字符串引用指向同一个字符串,则无需执行字符-逐字符比较以确定它们是否相同)。
对于某些情况,系统提供的字符串实习工具可能很有用。但是,它有几个严重的限制:
- 一旦一个字符串被实习,这个实习副本将永远存在,无论是否存在对它的任何其他引用
- 字符串实习工具仅适用于字符串,不适用于任何其他不可变类型。
如果存在一个 true WeakDictionary<ImmutableClassType, ImmutableClassType>
(对于每个元素,键和值都是相同的),代码可以执行以下操作:
不幸的是,我不知道.net 中有任何内置WeakDictionary<keyType, valType>
类。此外,为每个项目的键和值生成弱引用似乎很浪费,因为这两个引用总是指向同一事物。
我已经阅读了一些关于的内容ConditionalWeakTable
,这听起来像是一个有趣的类,但我认为它在这里不可用,因为目标是能够获取一个实例并找到另一个在语义上等效的独立实例。
对于类的实例将具有明确定义的生命周期的情况,使用常规Dictionary
来合并相同的实例可能是合理的。然而,在许多情况下,可能很难知道什么时候Dictionary
应该放弃这样的物品或清理其中的物品。基于实习的WeakReference
集合将避免此类问题。这样的事情是否存在,或者它是否可以很容易地实施?
附录
正如 svick 所指出的,aDictionary<WeakReference, WeakReference>
会有些问题,因为没有实用的方法来定义IEqualityComparer
一个活WeakReference
的返回GetHashCode
其目标的值,而死的继续返回该值。可以定义一个结构,该结构将包含一个整数目标哈希码值(在构造函数中设置),并且其自己的GetHashCode
将返回该整数。一个轻微的改进可能是使用 aConditionalWeakTable
将 的目标链接WeakReference
到可用于将表项排入队列以进行删除的可终结对象。
我不确定在急切地清理字典与采取更被动的方法(例如,如果自上次扫描以来至少有一个 GC,则在添加项目时执行扫描,以及数量自上次扫描以来添加的项目数超过了幸存的项目数)。浏览字典中的所有内容不会是免费的,但 ConditionalWeakTable 可能也不会是免费的。
PPS
我正在考虑的另一个概念,但我认为它可能不如弱实习方法有用,它是让一个逻辑上不可变的类型拥有一个可变的“时间戳”值,并有一个接受的比较方法它的论点由ref
. 如果发现两个不同的实例相等,则将检查它们的时间戳值。如果两者都为零,则将从全局计数器(-1、-2、-3 等)为它们分配连续的负数。具有(或分配)较低时间戳值的参数将被另一个替换。
使用这种方法,如果许多对象实例被重复地相互比较,许多引用将被替换为对“旧”实例的引用。根据使用模式,这可能会导致大多数相同的对象实例在不使用任何类型的实习字典的情况下被合并。然而,对嵌套对象应用这种方法将需要“不可变”对象允许嵌套对象引用被变异以指向其他假定相同的嵌套对象。如果“假定相同”的对象总是存在,这应该没问题,但如果不是,可能会导致相当奇怪的不当行为。
java - Java 字符串实习的替代方案
由于 Java 的默认字符串实习受到了很多负面报道,因此我正在寻找替代方案。
你能推荐一个 API 来替代 Java 字符串实习吗?我的应用程序使用 Java 6。我的要求主要是通过实习避免重复字符串。
关于坏消息:
- 字符串实习生是通过本机方法实现的。并且 C 实现使用一些 1k 条目的固定大小,并且对于大量字符串的扩展性非常差。
- Java 6 将实习字符串存储在 Perm gen 中。因此不是 GC'd 并可能导致 perm gen 错误。我知道这在 java 7 中已修复,但我无法升级到 java 7。
为什么我需要使用 intering?
- 我的应用程序是一个堆大小为 10-20G 的服务器应用程序,用于不同的部署。
- 在分析过程中,我们发现数十万个字符串是重复的,我们可以通过避免存储重复的字符串来显着提高内存使用率。
- 内存一直是我们的瓶颈,因此我们将其作为目标,而不是进行任何过早的优化。
c++ - 用于字符串实习的容器
我的目标是进行字符串实习。为此,我正在寻找一个可以执行以下操作的散列容器类:
- 每个节点只分配一块内存
- 每个节点不同的用户数据大小
值类型如下所示:
每个 String 对象都有不同的大小。这将通过 operator new + Placement new 来完成。所以基本上我想自己分配Node,稍后再推入容器中。
以下容器不适合:
- std::unordored_set
boost::multi_index::*
无法分配不同大小的节点
boost::intrusive::unordered_set
一开始似乎有效。但有一些缺点。首先,您必须自己分配存储桶数组并维护负载因子。这只是不必要且容易出错。
但另一个问题更难解决:您只能搜索具有 String 类型的对象。但是每次查找条目时分配一个字符串效率低下,并且您只有一个 std::string 作为输入。
是否有任何其他散列容器可用于此任务?
java - Java字符串实习,有什么保证?
问题归结为这段代码:
Java 标准是否对和的值提供任何保证?当然,链接到 Java 规范的相关部分会很好。case1
case2
是的,我查看了 SO 找到的所有“类似问题”,但没有发现重复项,因为我发现没有人以这种方式回答了这个问题。不,这不是关于通过替换来“优化”字符串比较的错误equals
想法==
。
python - Python字符串实习
虽然这个问题在实践中没有任何实际用途,但我很好奇 Python 如何进行字符串实习。我注意到以下内容。
这正如我所料。
你也可以这样做。
这很聪明!
但你不能这样做。
为什么 Python 不会评估s1+"g"
,并意识到它与相同s2
并将其指向相同的地址?最后一个区块实际上发生了什么让它返回False
?
c# - CompilationRelaxations.NoStringInterning 实际上是如何工作的?
我在演示 NoStringInterning 时遇到问题
我已经尝试使用 .NET CLR 2、3、4.. 作为输出,我得到的只是一堆 True。我期待一堆假!
java - Java - 反编译时字符串等于
前几天我反编译了一些Java代码,发现了这个:
显然使用 '==' 来测试字符串是否相等是不好的
但我想知道——这段代码已经被编译和反编译了。如果所有字符串都已在编译时定义并已实习并且代码已编译 - s1.equals(s2) 是否有可能已优化为“s1 == s2”?