equals()・hashCode() と同様にオブジェクトの比較に使用できる、compareTo() メソッドについて記述します。
compareTo() メソッドとは?(概要)
オブジェクト同士を比較し、どちらが大きいか小さいかを比較することが目的です。
equals() メソッドは、オブジェクト同士が等しいか等しくないかは確認できますが、どちらが大きいか小さいかまではわかりません。
そこで、compareTo() メソッドが必要になってきます。
compareTo() メソッドの仕様
まず、java.lang.Comparable インターフェースを実装することが大前提です。
その上で、以下の仕様に従う必要があります。
- this > argument ならば、正の値(通常+1)を返す。
- this = argument ならば、ゼロを返す。
- this < argument ならば、負の値(通常−1)を返す。
compareTo() メソッドの規約
上記仕様に加えて、compareTo() メソッドの実装は、以下の規約に従わなければなりません。
- a.compareTo(b) = - (b.compareTo(a)) であること。(symmetry)
- a.compareTo(b) > 0 かつ b.compareTo(c) > 0 ならば、a.compareTo(c) > 0 となること。(transitivity)
- a.compareTo(b) = 0 ならば、a.compareTo(c) = b.compareTo(c) となること。(reflexivity)
- a.compareTo(b) = 0 ならば、a.equals(b) = true となること。(必須ではないが推奨)
- 引数が異なるクラスの場合、ClassCastException をスローすること。
- 引数が null の場合、NullPointerException をスローすること。
compareTo() メソッドの役割
コレクション・フレームワークの(java.util.Collection、List/Set/Map)の一部で、格納されている値同士の比較に使用されています。
【具体的なクラス】
- TreeSet
- TreeMap
- Collections
- Arrays
なお、HashMap などでは、compareTo() メソッドではなく hashCode() メソッドを使用しています。
実装例
equals() メソッドの説明で使用した ComplicateObject を元に、compareTo() メソッドの実装例を記します。
import java.util.Date; // ●implements の仕方に注目 public class ComplicateObject implements Comparable{ // fields private boolean booleanValue; private byte byteValue; private char charValue; private short shortValue; private int intValue; private long longValue; private float floatValue; private double doubleValue; private String stringValue; private Date dateValue; public int compareTo(ComplicateObject target) { // ●float/double に注意(== ではなく compare() メソッドで判断すること) if (target == null) { // 引数が null の場合、比較する必要なし。 throw new NullPointerException(); } // ●booleanValue if (this.booleanValue == true && target.booleanValue == false) { return 1; } if (this.booleanValue == false && target.booleanValue == true) { return -1; } // ●byteValue if (this.byteValue > target.byteValue) { return 1; } if (this.byteValue < target.byteValue) { return -1; } // ●charValue if (this.charValue > target.charValue) { return 1; } if (this.charValue < target.charValue) { return -1; } // ●shortValue if (this.shortValue > target.shortValue) { return 1; } if (this.shortValue < target.shortValue) { return -1; } // ●intValue if (this.intValue > target.intValue) { return 1; } if (this.intValue < target.intValue) { return -1; } // ●longValue if (this.longValue > target.longValue) { return 1; } if (this.longValue < target.longValue) { return -1; } // ●floatValue int floatDiff = Float.compare(this.floatValue, target.floatValue); if (floatDiff > 0) { return 1; } if (floatDiff < 0) { return -1; } // ●doubleValue int doubleDiff = Double.compare(this.doubleValue, target.doubleValue); if (doubleDiff > 0) { return 1; } if (doubleDiff < 0) { return -1; } // ●stringValue if (this.stringValue != null && target.stringValue == null) { return 1; } if (this.stringValue == null && target.stringValue != null) { return -1; } if (this.stringValue != null && target.stringValue != null) { int stringDiff = this.stringValue.compareTo(target.stringValue); if (stringDiff > 0) { return 1; } if (stringDiff < 0) { return -1; } } // ●dateValue if (this.dateValue != null && target.dateValue == null) { return 1; } if (this.dateValue == null && target.dateValue != null) { return -1; } if (this.dateValue != null && target.dateValue != null) { int dateDiff = this.dateValue.compareTo(target.dateValue); if (dateDiff > 0) { return 1; } if (dateDiff < 0) { return -1; } } // いずれの値も等しかった場合 return 0; } // getter/setter/constructor は省略 }