Java – 配列 – 同一性・等価性

概要

配列の同一性は変数が指しているインスタンスが同じかどうかのみによるが、等価性の場合は末端の要素一つ一つが等価かどうかを判定することになる。

Javaの配列で等価性を判定する場合、1次元配列はArrays.equals()で等価性を判定できるが、2次元以上の配列になるとArrays.deepEquals()で判定しなければならない。

配列のコピーでもディープコピーができるメソッドがなくループで回さないといけないなど、Javaの配列は使いにくい。というよりも、下手に使うと思わぬところでミスの要因になりそう。

1次元配列

同一性(==)

配列変数が指している対象が同じかどうか。内容が同じでも変数が指しているインスタンスが異なる場合は同一にならない。

以下の例ではarray1array2が同じ配列インスタンスを指している(ハッシュ値が等しい)ので、内容が変わっても同一。

一方で変更前のarray1array4、変更後のarray1array3は、内容が同じでも配列のインスタンスが異なるため、同一とは判定されない。

等価性(Array.equals)

配列の内容が同じかどうか。異なる配列インスタンスでも内容が同じなら等価。同値性とも。

配列の等価性をチェックするにはArrays.equals()メソッドを使う。

以下の例では、array1array2は同一であり等価。array1の変更前はarray3と等価だが、変更後にはarray4と等価になる。

equals()メソッドは要注意

配列もオブジェクトとしてequals()メソッドを備えているが、これは同一性の判定しかせず、等価性の判定には使えない。

以下の例で、結果が==のときと同じになっているのが確認できる。

多次元配列

Array.equals()も要注意

Arrays.equals()clone()の挙動と似ていて、

  • 1次元目の各要素が同一なら結果はtrue
  • 1次元目の各要素のいずれかが同一でないなら結果はfalse

多次元配列でArray.equals()を使うと、2次元目の要素配列が同一であればtrueとなり、同一でなければ内容が同じでもfalseとなる。

以下の例では、

  • array2d1array2d2は元のインスタンスが同一であり等価
  • array2d1からclone()で作られたarray2d3は、元のインスタンスは異なるが、それが指している要素が同じなので同一ではないが等価
  • array2d3array2d4も、元のインスタンスから要素に至るまでarray2d1と異なるため、変更前/変更後に内容が同じになっても等価と判定されない

Arrays.equals()の等価性判定は1次元配列にしか使えない

深層比較(deepEquals)

Arrays.deepEquals()は、引数の2つの配列の要素の等価性を再帰的に判定する。

 

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です