Java比較メソッド一発理解!

Java_比較メソットについて Java

Javaで値を比べようと==equals()を使ってみたら、思わぬ結果が返ってきて混乱したことはありませんか?

私も最初、文字列同士を==で比べて「同じはずなのにfalse!」と何度も悩みました。

本記事では、==equals()の違いから、独自クラスでのequals()実装、プリミティブとラッパーの比較、文字列比較メソッドの選び方、コレクション内での重複判定まで、やさしい例とともに徹底解説します。

「この記事を読んだら、オブジェクト比較の謎がスッと解けた!」という声が多数。

new String("a")==new String("a")false になる理由や、ArrayList.contains() の動作原理もクリアに理解できます。

今すぐ読み進めて、バグのない安全な比較コードを書けるようになりましょう!

== と equals() の違いがわからない

== は「同じ場所か」を比べ、equals() は「中身が同じか」を比べます。

Javaでオブジェクト同士を==で比べると、同じインスタンスでなければfalseになります。equals()はクラスごとに中身の比較ロジックを書けるため、値の同一性を判断したいときに使います。
具体例を見てみましょう!

String a = new String("Hello");
String b = new String("Hello");
System.out.println(a == b);       // false、別オブジェクト
System.out.println(a.equals(b));  // true、中身は同じ

Integer x = 128;
Integer y = 128;
System.out.println(x == y);       // false、ボクシングで別オブジェクト
System.out.println(x.equals(y)); // true、中身は同じ

オブジェクトを比較するときは必ずequals()を使い、==はプリミティブ型や参照同一性のチェックに限定しましょう。

equals() をオーバーライドする方法がわからない

自作クラスで中身比較を行うには、equals()hashCode() を正しくオーバーライドする必要があります。

コレクション(Set, Mapなど)はequals()hashCode()で要素の同一性を判断します。これを書かないと、同じ値を持つオブジェクトが別扱いされてしまいます。
例えば!

public class Person {
  private String name;
  private int age;

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Person)) return false;
    Person p = (Person) o;
    return age == p.age && name.equals(p.name);
  }

  @Override
  public int hashCode() {
    return Objects.hash(name, age);
  }
}

これで new Person("Alice",20).equals(new Person("Alice",20))true になります。

equals()hashCode() はセットでオーバーライドし、中身比較のルールをクラス定義に組み込みましょう。

プリミティブ型とラッパークラスの比較ミスをなくす

int なら ==Integer なら equals() で比較します。

ラッパークラスはオブジェクトなので、== は参照比較になります。ヌル値を扱うとき、equals() ではNullPointerExceptionに注意が必要です。

int a = 5;
int b = 5;
System.out.println(a == b);      // true, プリミティブ比較

Integer x = 5;
Integer y = 5;
System.out.println(x == y);      // true (キャッシュ範囲内)

Integer m = 128;
Integer n = 128;
System.out.println(m == n);      // false (キャッシュ外)
System.out.println(m.equals(n)); // true

ヌル値を安全に比較するには、Objects.equals(x, y) がおすすめです。

プリミティブは ==、ラッパーは equals() で、ヌル対策には Objects.equals() を使いましょう。

文字列比較で equalsIgnoreCase() と compareTo() の使い分け

大文字小文字を無視するときは equalsIgnoreCase()、辞書順に並べたいときは compareTo() を使います。

equalsIgnoreCase() は文字列同士の同一性を大文字小文字を区別せずにチェック。compareTo() は辞書順比較を行い、ソートや範囲チェックに適しています。
具体例を見てみましょう!

String s1 = "Java";
String s2 = "java";
System.out.println(s1.equalsIgnoreCase(s2)); // true

String[] arr = {"banana","Apple","cherry"};
Arrays.sort(arr); // デフォルトは compareTo()、大文字優先
System.out.println(Arrays.toString(arr));

大文字小文字無視ソートは String.CASE_INSENSITIVE_ORDER を使えます。

同一性チェックか順序比較かでメソッドを選び、使い分けると文字列操作が正確になります。

コレクションの要素比較と重複判定を理解する

List.contains()Set の重複判定は equals()hashCode() に依存します。

コレクション内部では、要素同士を equals() で比べ、ハッシュ構造なら hashCode() も使います。これが未実装・誤実装だと重複判定が壊れます。
例えば!

Set<Person> set = new HashSet<>();
set.add(new Person("Bob",30));
set.add(new Person("Bob",30));
System.out.println(set.size()); // equals/hashCode 未実装なら2, 実装済みなら1

コレクションを使う前に、自作要素クラスの equals()hashCode() を確実に実装しましょう。

まとめ:等価判定を正しく使い分けてバグを防ごう

  1. 参照比較と値比較== はアドレス、equals() は中身を比べる。
  2. equals/hashCode オーバーライド:自作クラスの中身比較ルールを定義。
  3. プリミティブ vs ラッパー:基本は == vs equals()Objects.equals() でヌル対策。
  4. 文字列比較メソッド:同一性は equalsIgnoreCase()、順序比較は compareTo()
  5. コレクション重複判定contains()Set は equals/hashCode に依存。

これらを理解し、適切な比較方法を選べば、等価判定に起因するバグをぐっと減らせます。今日学んだことをコードで試し、安全で正確なJavaプログラムを書きましょう!

タイトルとURLをコピーしました