2015-11-06 1 views
11

String.equals道具String.equals実装

public boolean equals(Object anObject) { 
    if (this == anObject) { 
     return true; 
    } 
    if (anObject instanceof String) { 
     String anotherString = (String)anObject; 
     int n = value.length; 
     if (n == anotherString.value.length) { 
      char v1[] = value; 
      char v2[] = anotherString.value; 
      int i = 0; 
      while (n-- != 0) { 
       if (v1[i] != v2[i]) 
        return false; 
       i++; 
      } 
      return true; 
     } 
    } 
    return false; 
} 

などの反復は二つの動作使用しない理由 - iをインクリメントし、代わりにそのような何かのnをデクリメント:

while (i < n) { 
    if (v1[i] != v2[i]) 
     return false; 
    i++; 
} 

または

while (i-- != 0) { 
    if (v1[i] != v2[i]) 
     return false; 
} 

1つのインクリメントtまたは減少操作?

JVMのバイトコードの最適化とは何とか関係していますが、その仕組みはわかりません。

+1

[関連] [関連](http://stackoverflow.com/q/12661335/1743880) – Tunaki

+1

@Thiloそうです。その点を逃した。 – SubOptimal

+0

これは何らかの巧妙な最適化(どのように見えないか)の場合、 'Arrays.equals'に使用しないことに決めたものです。 'Arrays.equals'は明白な' for'ループを使います。 –

答えて

5

これはデッドコードだと思いますが、Stringsが引き続き配列を共有していて、offsetcountの文字列を共有していた時から残して、インデックスを少し調整する必要がありました。

JDK 7 Update 6では文字列の実装が変更されました(多くの人が気になっていましたが、特にマイナーリリースで発生しました)。ストリングはそれ以上バッキング配列を共有しません(ストリング自体が等しい場合を除き、新しい重複除外機能がそれらを再共有しようとする場合)。

how does String.equals() work」の古い実装についての説明があります。

+1

もう一つ興味深い点は、equalsはStringsのhashCodeを使用しないことです。これはhttp://stackoverflow.com/questions/14262431/why-does-the-equals-method-in-string-not-use-hash?lq=1 – Thilo

+0

で議論されています。そして、配列はもはや共有されていないので、 2つの配列のオブジェクトの同一性を比較することもできます( 'if(value == anotherString.value)return true')。それはあまり起こらないと思います。 – Thilo

+0

弦のアイデンティティを比較するときに、すでにそれをしていませんか? –

0

実際には、このJavaコードは実際のマシンコードと直接関係しません(少なくとも現代のデスクトップ/サーバーJVMでは)。 「HotSpot VMの組み込みメソッド」について読むことができます。例えば。 When will JVM use intrinsics