在Java中,显式声明的字符串由JVM实现,因此相同String的后续声明会产生两个指向同一String实例的指针,而不是两个单独的(但相同的)字符串.
例如:
public String baz() {
String a = "astring";
return a;
}
public String bar() {
String b = "astring"
return b;
}
public void main() {
String a = baz()
String b = bar()
assert(a == b) // passes
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,CPython(或任何其他Python运行时)对字符串做同样的事情吗?例如,如果我有一些课程:
class example():
def __init__():
self._inst = 'instance'
Run Code Online (Sandbox Code Playgroud)
并创建此类的10个实例,它们中的每一个都有一个实例变量引用内存中的相同字符串,或者我最终会得到10个单独的字符串?
我试过下面的代码:
public class TestIntern {
public static void main(String[] args) {
char[] c1={'a','b','h','i'};
String s1 = new String(c1);
s1.intern();
String s2="abhi";
System.out.println(s1==s2);//true
char[] c2={'j','a','v','a'};
String sj1 = new String(c2);
sj1.intern();
String sj2="java";
System.out.println(sj1==sj2);//false
char[] c3={'J','A','V','A'};
String tj1 = new String(c3);
tj1.intern();
String tj2="JAVA";
System.out.println(tj1==tj2);//true
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试了很多不同的文字.
任何人都可以解释为什么intern()不能按字面意思的方式工作"java"?为什么上面的参考比较要评估true,除非文字是"java"?
我试图理解字符串实习,为什么在我的例子中似乎不起作用.示例的要点是显示示例1使用较少(内存较少),因为它在内存中应该只有10个字符串.但是,在下面的代码中,两个示例都使用大致相同的内存量(虚拟大小和工作集).
请告知为什么示例1没有使用更少的内存?谢谢
例1:
IList<string> list = new List<string>(10000);
for (int i = 0; i < 10000; i++)
{
for (int k = 0; k < 10; k++)
{
list.Add(string.Intern(k.ToString()));
}
}
Console.WriteLine("intern Done");
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)
例2:
IList<string> list = new List<string>(10000);
for (int i = 0; i < 10000; i++)
{
for (int k = 0; k < 10; k++)
{
list.Add(k.ToString());
}
}
Console.WriteLine("intern Done");
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud) 我前几天反编译了一些Java代码并发现了这个:
String s1 = "something";
String s2 = "something_else";
if (s1 == s2) {
// Path 1
} else {
// Path 2
}
Run Code Online (Sandbox Code Playgroud)
显然使用'=='来测试字符串相等是不好的
但我想知道 - 这段代码已被编译和反编译.如果在编译时已经定义了所有字符串并且已经编译并且代码已经编译 - 是否可能s1.equals(s2)已经优化到's1 == s2'?
我有一种情况,我会遇到很多重复的字符串,这些字符串会在内存中持续很长时间.我想使用,String.Intern但我不想入侵任何潜在的应用程序资源,因为我的项目是一个库.这是如何运作的?
我有一个大文件,其本质上包含如下数据:
Netherlands,Noord-holland,Amsterdam,FooStreet,1,...,...
Netherlands,Noord-holland,Amsterdam,FooStreet,2,...,...
Netherlands,Noord-holland,Amsterdam,FooStreet,3,...,...
Netherlands,Noord-holland,Amsterdam,FooStreet,4,...,...
Netherlands,Noord-holland,Amsterdam,FooStreet,5,...,...
Netherlands,Noord-holland,Amsterdam,BarRoad,1,...,...
Netherlands,Noord-holland,Amsterdam,BarRoad,2,...,...
Netherlands,Noord-holland,Amsterdam,BarRoad,3,...,...
Netherlands,Noord-holland,Amsterdam,BarRoad,4,...,...
Netherlands,Noord-holland,Amstelveen,BazDrive,1,...,...
Netherlands,Noord-holland,Amstelveen,BazDrive,2,...,...
Netherlands,Noord-holland,Amstelveen,BazDrive,3,...,...
Netherlands,Zuid-holland,Rotterdam,LoremAve,1,...,...
Netherlands,Zuid-holland,Rotterdam,LoremAve,2,...,...
Netherlands,Zuid-holland,Rotterdam,LoremAve,3,...,...
...
Run Code Online (Sandbox Code Playgroud)
这是一个数千兆字节的文件.我有一个类读取此文件并将这些行(记录)公开为IEnumerable<MyObject>.这MyObject有几个属性(Country,Province,City,...)等.
如您所见,存在大量重复数据.我想继续公开底层数据IEnumerable<MyObject>.但是,其他一些类可能(并且可能会)对这些数据进行一些分层视图/结构,如:
Netherlands
Noord-holland
Amsterdam
FooStreet [1, 2, 3, 4, 5]
BarRoad [1, 2, 3, 4]
...
Amstelveen
BazDrive [1, 2, 3]
...
...
Zuid-holland
Rotterdam
LoremAve [1, 2, 3]
...
...
...
...
Run Code Online (Sandbox Code Playgroud)
在阅读这个文件时,我基本上就是这样做的:
foreach (line in myfile) {
fields = line.split(",");
yield return new MyObject {
Country = fields[0], …Run Code Online (Sandbox Code Playgroud) 在早期版本的Python中(我不记得哪个),gc.get_referrers可以使用对任意实习字符串的调用来获取对interneddict 的引用,然后可以查询其长度.
但是这不再适用于Python 2.7.5:gc.get_referrers(...)不再包含interned它返回的列表中的dict.
在Python 2.7.5中,有没有其他方法来确定实习字符串的数量?如果是这样,怎么样?
Python是否拥有所有字符串的池并且它们是(字符串)单例吗?
更准确地说,在下面的代码中,在内存中创建了一个或两个字符串:
a = str(num)
b = str(num)
Run Code Online (Sandbox Code Playgroud)
?
问题归结为这段代码:
// setup
String str1 = "some string";
String str2 = new String(str1);
assert str1.equals(str2);
assert str1 != str2;
String str3 = str2.intern();
// question cases
boolean case1 = str1 == "some string";
boolean case2 = str1 == str3;
Run Code Online (Sandbox Code Playgroud)
Java标准是否对和的值有任何保证?当然,链接到Java规范的相关部分会很好.case1case2
是的,我查看了SO发现的所有"类似问题",发现没有重复,因为没有我发现这样回答了问题.不,这不是关于更换"优化"的字符串比较的误导想法equals用==.
string-interning ×10
string ×7
c# ×3
java ×3
python ×3
.net ×2
cpython ×1
equality ×1
hashset ×1
memoization ×1
memory ×1
optimization ×1
singleton ×1