我正在查看java.lang.String
的来源,并注意到equals
method没有检查支持每个String的char[]
是否是同一个对象。这不会改善比较时间吗?
此重写版本中包含的改进:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
/** Begin Optimization **/
if(v1==v2 && i==j){
return true;
}
/** End Optimization **/
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
我认为,如果使用String.substring
获得两个字符串,甚至可能实际使用字符串,这可以提高性能。
有人知道他们选择不以这种方式实施的原因吗?
更新:对于可能对implementation of String可能不太了解的任何人,除了String池之外还有两个String对象可以具有相同的char []值的情况,int offset和int count。
请考虑以下代码:
String x = "I am a String, yo!";
String y = x.split(" ")[3];
String z = x.substring(7,14);
你最终会遇到这样的情况:
显然,在Java 7u6中,Strings的价值共享功能已被废除,以满足一些基准测试。因此,如果您花时间使用String.substring()而不是字符串连接来使代码在适当的时间(或根本)运行,那么您就是SOL。
答案 0 :(得分:1)
嗯,您需要检查char[]
,offset
和 count
(字符串长度)。由于char[]
仅在String
类中创建,因此所有这三个相等的唯一方法是String
从自身创建doppelgänger。你可以这样做(例如new String("why?")
),但这不是一个常见的用例。
<speculative>
我甚至不确定它是否能加快速度。在绝大多数情况下,检查将失败,这意味着它正在做额外的工作,没有任何好处。这可以通过分支预测来抵消,但是在 情况下,检查通过的次数很少,它将使该分支预测所做的猜测无效,这实际上可能会使事情变慢。换句话说,如果JVM / CPU尝试针对常见情况进行优化,那么您通常什么也得不到,并且在极少数情况下(实际上您正在尝试优化)实际上会让您自己受伤。如果它没有尝试优化这种常见情况,那么为了进行相当罕见的比较,你会在大多数比较中伤害自己。 </speculative>
答案 1 :(得分:0)
在Java 7中(see this article),substring()
不再对返回的String
使用相同的后备数组。你仍然需要检查每个角色。基本上,String
支持char[]
永远不会共享,因此您无法
this.value == other.value
答案 2 :(得分:0)
我不明白这个问题
char[]
是String
的内部成员。如果2个String引用是相同的(应该是因为你应该使用实习字符串)char []将是相同的
但是对于不同的实例,为什么你期望char[]
是相同的参考?字符串是不可变的,并且2个不同的String对象不可能共享对同一个支持的数组的引用
另外,即使对于子串也使用这种条件检查甚至没有意义
我不知道其中一个答案中提到的Java 7的变化,但在这种情况下检查备份阵列的相等性是错误的。
String对象不仅是后备数组,还有当前的偏移量,长度等
因此,作为子字符串结果的2个String对象可以由相同的char数组支持,但可以很好地包含不同的(子)字符串作为内容 - 不同相同的字符数组
答案 3 :(得分:0)
对后备字符数组进行此类检查很可能是多余的,不是必需的。
有两个实例,后备字符数组对象可以是相同的对象(因为其他指向子字符串方法总是创建一个新的后备字符数组)。
定义字符串文字
String a = "Hello";
a.equals("Hello"); // Backing array of "Hello" string literal
// will be same as that of variable a
在这种情况下,即使在检查后备字符数组之前,equals方法也会确定String在以下行中是否相等。
if (this == anObject) { // From String.equals method
return true;
}
使用String copy构造函数创建另一个String对象
请注意,以下代码块没有实际价值,因此无法在实际代码中完成。
String a = "Hello;
String b = new String(a);
a.equals(b);
因此,如果String对象不同,可以安全地假设它们总是不同的,而不是进行额外的检查以确定字符数组是否相同。