6

我正在查看源代码java.lang.String并注意到该equals方法不会检查char[]每个 String 的支持是否是同一个对象。这不会改善比较时间吗?

此重写版本中包含的假设改进:

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甚至可能是实习字符串。

有谁知道他们选择不以这种方式实施它是否有原因?

更新: 对于可能不太了解String 实现的任何人,除了 String 池之外,还有两个 String 对象可以具有相同的 char[] 值、int 偏移量和 int 计数的情况。

考虑以下代码:

String x = "I am a String, yo!";
String y = x.split(" ")[3];
String z = x.substring(7,14);

你最终会遇到这样的情况: 调试器表达式

显然,字符串的值共享功能在 Java 7u6 中已被取消,以满足某些基准。因此,如果您花时间通过使用 String.substring() 而不是字符串连接来让代码在适当的时间(或根本)运行,那么您就是 SOL。

4

4 回答 4

1

好吧,您需要检查char[]、 theoffset count字符串长度)。由于char[]仅从String类内部创建,因此所有三个相等的唯一方法是Stringa 从自身创建一个分身。你可以让它做到这一点(例如new String("why?")),但这不是一个常见的用例。

<speculative>我什至不确定它是否会加快速度。绝大多数情况下,检查都会失败,这意味着它正在做额外的工作而没有任何好处。这可能会被分支预测所抵消,但在这种情况下,检查通过的几次,它将使该分支预测所做的猜测无效,这实际上可能会减慢速度。换句话说,如果 JVM/CPU 尝试针对常见情况进行优化,您通常不会获得任何收益,并且在极少数情况下您实际上会伤害自己(这就是您要优化的情况)。如果它不尝试优化该常见情况,那么您会在大多数比较中为了一组相当罕见的比较而伤害自己。</speculative>

于 2013-09-18T20:05:54.467 回答
0

对后备字符数组进行这样的检查很可能是多余的,并且不是必需的。

有两个实例支持字符数组对象可能是相同的对象(因为其他指向的子字符串方法总是创建一个新的支持字符数组)。

定义字符串文字

String a = "Hello";
a.equals("Hello"); // Backing array of "Hello" string literal 
                   // will be same as that of variable a

在这种情况下,equals 方法将在检查后备字符数组之前确定字符串在下一行是否相等。

if (this == anObject) { // From String.equals method
    return true;
}

使用 String 复制构造函数创建另一个 String 对象

请注意,以下代码块没有实际价值,并且永远无法在实际代码中完成。

String a = "Hello;
String b = new String(a);
a.equals(b);

因此,与其做额外的检查来确定字符数组是否相同,不如假设如果 String 对象不同,它们总是不同的。

于 2013-09-18T21:17:14.387 回答
0

在 Java 7参见这篇文章)中,substring()不再使用相同的后备数组来返回String. 您仍然需要检查每个字符。基本上,String支持char[]永远不会共享,所以你不能

this.value == other.value
于 2013-09-18T20:03:56.170 回答
0

我不明白这个问题。
是的char[]内部成员String。如果 2 个字符串引用相同(应该是因为您应该使用实习生字符串),则 char[] 将是相同的。
但是对于不同的情况,您为什么期望char[]是相同的参考?字符串是不可变的,2 个不同的 String 对象不可能共享对同一个支持数组的引用。
此外,即使对子字符串使用这种条件检查也没有任何意义。
我不知道其中一个答案中提到的 Java 7 的变化,但在这种情况下检查支持数组的相等性是错误的。
String 对象不仅是支持数组,而且是它的当前偏移量、长度等。
因此,作为子字符串的结果的 2 个字符串对象可能由相同的 char 数组支持,可以很好地包含不同的(子)字符串作为内容 -同一个char 数组中的不同偏移量

于 2013-09-18T20:44:45.107 回答