Javaについて徹底解説!

JavaのcompareToとは?ソートを自由自在に操るためのcompareToの使い方

大石 英人

大石 英人

開発エンジニア/Java20年/Java GOLD/リーダー/ボールド歴2年

JavaのインターフェイスComparableのメソッドcompareToでは、大小比較を行います。このインターフェイスを実装したクラスは大小比較ができるようになり、結果、ソートを行えるようになるのです。

どんなプログラムでも、ソートは欠かせない処理です。JavaのソートはこのComparableと、もう一つの大小比較のインターフェイスであるComparatorが支えています。

この記事では、Comparable.compareToについて初心者向けに一から説明します。便利な使い方やComparatorとの使い分けについても説明しますので、ぜひ読んでいってください。

なお「compareToは後から勉強するので、今はとにかくソートのやり方を!!」という方は、「4.Comparableを使ったソート」がまさにそれです!!

※この記事のサンプルは、Java 10の環境で動作確認しています。

One dayインターン

1.Comparable.compareToはソートで使う

1-1.Comparable.compareToは大小比較をする

インターフェイスComparableの抽象メソッドcompareToは、自分自身と引数のクラスを大小比較した結果を整数で戻すメソッドです。

まずはcompareToの使い方と戻り値について、以下だけしっかりと覚えておけば、compareToを使う上ではバッチリです!!

使い方

   比較するもの.compareTo(比較されるもの)

   →大小比較した結果の整数が戻る

大小比較の結果

   比較するもの < 比較されるもの:-1以下の整数

   比較するもの = 比較されるもの:0

   比較するもの > 比較されるもの:1以上の整数

1-2.ソートには大小比較が必要不可欠!

配列やコレクションのソートは頻繁に使います。何かを日付別にソートしたり、集計結果の件数などで昇順/降順にソートしたりなどです。

そんなソートを行うには、配列やコレクションに格納されている要素同士の大小比較が必要です。バブルソート、マージソート、クイックソートなど、どんなソートアルゴリズムを使うにしても、大小比較は欠かせません。

intなどの数字なら大小比較は自明です。でもJavaはオブジェクト指向プログラミング言語なので、クラス同士の大小比較が必要ですが、クラスには数字のように自明な判断基準がないので、プログラマーが大小を教えてあげなければなりません。そのために使うのがComparable.compareTo()です。


2.Comparable.compareToのコツ

2-1.判断結果は小さい・等しい・大きいの3種類だけ

まずは、compareToがどういうものか見ていきましょう。Comparable.compareToのメソッド宣言は以下のようになっています。

int compareTo(T o)
	このオブジェクトと指定されたオブジェクトの順序を比較します。
パラメータ:
	o -比較対象のオブジェクト。
戻り値:
	このオブジェクトが指定されたオブジェクトより小さい場合は負の整数、等しい場合はゼロ、大きい場合は正の整数

ここで、実用上で意識すべきなのは、戻り値が0かどうか、そして0より大きいか小さいかです。

説明には負の整数・正の整数とありますが、単に0と比べて大きいのか小さいのかを知りたいだけすなわち3つの状態を区別したいだけなので、数字の絶対値自体には意味はありません。一般的には-101が使われますし、JDKのソースコードでも(大体は)同じです。

2-2.大小比較は相手より自分が大きいか小さいか

覚えておくべきなのは、比較「する」側と比較「される」側の関係です。比較する側のcompareToは、比較される側を引数に呼び出されます。大小比較の結果はこれを前提とした戻り値となります。

つまり、比較する側「から」見た視点になります。自分が比較される側より大きいか小さいか、あるいは同じかが、compareToの戻り値となります。

例えば、数値の50が比較する側、100が比較される側だとします。50からすると自分は100よりも「小さい」ので、戻り値は-1以下の整数になります。

2-3.IntegerでcompareToを試してみる

さて、前述のとおり、Comparableはインターフェイスなので、何かのクラスに実装(implements)しなければなりません。intのラッパークラスIntegerComparableを実装していますので、これでどういう結果になるか試してみます。

Integer zero = Integer.valueOf(0);
Integer zero2 = Integer.valueOf(0);
Integer one = Integer.valueOf(1);
Integer negativeOne = Integer.valueOf(-1);
Integer million = Integer.valueOf(1000000);

System.out.println(zero.compareTo(one)); // 0と1を比較する→0は1よりも小さい→「-1」が戻り値
System.out.println(zero.compareTo(negativeOne)); // 0と-1を比較する→0は-1よりも大きい→「1」が戻り値
System.out.println(one.compareTo(negativeOne)); // 1と-1を比較する→1は-1よりも大きい→「1」が戻り値
System.out.println(negativeOne.compareTo(one)); // -1と1を比較する→-1は-1よりも小さい→「-1」が戻り値
System.out.println(zero.compareTo(zero2)); // 0と0を比較する→0は0と同じ大きさ→「0」が戻り値
System.out.println(zero.compareTo(million)); // 0と1000000を比較する→-1、差がいくら大きくても戻り値が0より小さければいい!!

きちんとメソッドの仕様どおりの戻り値になっていますね。これがcompareToの動きです。Comparableを実装している同じクラス同士なら、全てこのように大小比較ができるのです。

※「6.【参考】Java標準APIのクラスでのcompareToについて」に、Integer以外のJava標準APIの良く使うクラスでcompareToを行った場合にどうなるかを記載してあります。


3.Comparable.compareToの実装例

3-1.compareToの基本形

前章ではcompareToをIntegerなどで試してみました。次は自分で作ったクラスでcompareToしてみましょう。以下は何かのユーザ(User)のつもりで、int noはユーザごとの番号です。この番号をキーにcompareToしてみます。

class User implements Comparable {
	int no;

	User(int no) {
		this.no = no;
	}

	public int compareTo(Object o) {
		User u = (User) o;

		// 自分の方が比較先より「小さい」なら負の整数を返す
		if (this.no < u.no) {
			return -1;
		}

		// 自分の方が比較先より「大きい」なら正の整数を返す
		if (this.no > u.no) {
			return 1;
		}

		// ここに来るということは比較先と「等しい」ので、0を返す
		return 0;
	}

	public static void main(String[] args) {
		User u1 = new User(1);
		User u2 = new User(2);
		User u3 = new User(3);

		System.out.println(u1.compareTo(u2)); // -1、番号1と2を比較した結果
		System.out.println(u3.compareTo(u1)); // 1、番号3と1を比較した結果
		System.out.println(u1.compareTo(u1)); // 0、u1同士で比べるなら、同じ番号(両方1)なので
	}
}

これがcompareToの基本形です。compareToの引数は比較先の何かのインスタンスです。でも、型がObjectのままでは比較しようがないので、自分自身のクラスにキャストしてから比較に使う値を参照し、大小比較の結果を戻します。

この例では整数の常識に従った大小比較をしています。でも、これは皆さんの好きにできるJavaのプログラムですので、いかようにも大小比較のルールを自分で設定できるのです!! 大小比較の結果、正負の整数と0のどれかを戻すというルールを守りさえすればいいのです。

例えば、このクラスの大小比較結果を番号の「降順」としたいなら、大小比較で戻す整数の正負を逆転させるだけです。

	public int compareTo(Object o) {
		User u = (User) o;

		// 実態がどうであれ、判断結果は戻り値が全て
		// 相手の方が大きければ、自分の方が「大きい(1)」と返す
		if (this.no < u.no) {
			return 1;
		}

		// 整数の降順にしたいなら、相手の方が小さければ、自分の方が「小さい(-1)」と返す
		if (this.no > u.no) {
			return -1;
		}

		// 降順でも等しいということは変わらないので、0を返す
		return 0;
	}

なお、Comparableの型引数(<>の中にあるもの)をきちんと使うなら以下のようになるでしょう(以後はこの書き方で行きます)Java 1.5以降を使われているならこちらがお勧めです。

しかし、型引数を使ったとしても、行っていることは本質的には何も変わっていません。型引数を使うことでキャストの手間が省けるのと、型引数で指定したクラス以外をcompareToの引数にするとコンパイルエラーになるので、より安全性が高まったというくらいです。

class User implements Comparable<User> {
	int no = 0;

	User(int no) {
		this.no = no;
	}

	public int compareTo(User u) {
		if (this.no < u.no) {
			return -1;
		}

		if (this.no > u.no) {
			return 1;
		}

		return 0;
	}
}

3-2.複数の条件で大小比較をしたい場合

前節では一つの項目のみで大小比較をしてみました。実際のプログラミングでは複数の項目を組み合わせて大小比較をすることが多いので、そのようなものも実装してみましょう。

例として、先ほどのクラスUserに氏名(name)を追加して、氏名の昇順番号の降順で大小比較をするcompareToを実装してみます。

class User implements Comparable<User> {
	int no; // 番号
	String name; // 氏名

	User(int no, String name) {
		this.no = no;
		this.name = name;
	}

	public int compareTo(User u) {
		// 先に名前で大小比較をして…
		int ret = this.name.compareTo(u.name);

		// 名前で大小の違いがあるならそこで終了
		if (ret != 0) {
			return ret;
		}

		// 名前が同じなら番号で比較(降順なので符号を逆にするため -1 を掛ける)
		return Integer.compare(this.no, u.no) * -1;
	}

	public static void main(String[] args) {
		User u1 = new User(1, "山田太郎");
		User u2 = new User(100, "山田太郎"); // 同姓同名!

		System.out.println(u1.compareTo(u2)); // → 1!! 名前が同じなので番号で判断、1より100の方が大きいが、降順なので「1の方が100より大きい」
	}
}

最初にすべきは名前の大小比較です。StringはComparableですので、compareToを実行できます。名前が違えば(!= 0)大小は既に確定しましたので、比較結果でreturnします。

名前の大小比較が「等しい」なら、さらに番号で大小比較します。intである番号のcompareToの結果を正負反転させてreturnすれば、番号の降順の比較結果を戻すことになります。ここで、正負を反転させるために-1を掛けるのは、compareToでの常套手段です。

このように、複数の項目を組み合わせる場合は、compareToの中で一つ一つの項目の大小比較を行って結果を確認しながら、全体としての大小比較を行っていけばよいのです。

3-3.プリミティブ型の大小比較はcompareで楽しよう!

先ほどInteger.compare(int, int)というメソッドを使いました。これは、int同士の大小比較をcompareToの方法で実行した結果を返してくれるメソッドです。ですから、実は自分でわざわざif文を書かなくてもいいのです。楽ちんですね。

Java 7以降では、プリミティブ型のラッパークラスにはこのような便利な大小比較メソッドがあるので、どんどん活用しましょう。

// プリミティブ型ラッパークラスのcompareメソッド一覧
Byte.compare(byte, byte)
Short.compare(short, short)
Integer.compare(int, int)
Long.compare(long, long)
Float.compare(float, float)
Double.compare(double, double)
Character.compare(char, char)
Boolean.compare(boolean, boolean)

3-4.比較できないなら例外をthrowしよう

Comparable.compareToのJavadocをよく読むと、以下の記述があります。

例外:
	NullPointerException - 指定されたオブジェクトがnullの場合
	ClassCastException - 指定されたオブジェクトの型が原因で、このオブジェクトと比較できない場合

書いてあるのはもっともなことで、引数の比較先のインスタンスがnullなら比較のしようがありませんし、自分と関係のないクラスと比較することにも意味がありませんので、そんな場合は例外をthrowして「比較ができないよ」と表明します。

先のUserは自動的にそうなりますが、きちんと明示的にプログラムするなら以下のようになります。

	public int compareTo(Object o) {
		// 比較先がnullであるか確認する。※このif文はjava.util.Objects.requireNonNull(o)でも同じ
		if (o == null) {
			throw new NullPointerException();
		}

		// Userのインスタンスであるか確認する
		if (!(o instanceof User)) {
			throw new ClassCastException();
		}
	
		…以下同様…
	}
}

4.Comparableを使ったソート

さて、Comparable.compareToがどんなものか、どうプログラムすればいいのかをご理解いただいたところで、実際にComparableのソートをしてみましょう。

ここではComparableのサンプルとして、分かりやすさからStringを使います。でも、IntegerDateBigDecimalや、この記事で作成したUserのようなComparableを実装した任意のクラスでも同じやり方が使えます。要は、ソート対象がComparableでさえあればいいのです!

4-1.Arrays.sort(Object[])で配列をソートする

Comparableなものの配列をソートするなら、Arrays.sort(Object[])を使います。引数はObjectの配列ですが、事実上Comparableが実装されていて、かつ全要素が同じクラスのインスタンスでなければ、実行時に例外がthrowされます。

Arrays.sort(Object[])は「小さい」順にソートします。「大きい」順にソートしたい場合は少し工夫が必要で、Collections.reverseOrder()またはComparator.reverseOrder()を併用します。もちろん、小さい・大きいはComparableでプログラムしたとおりの順序になります。

このメソッドでは引数で与えた配列自体の並び順が変わります。ソートされた配列を戻り値で受け取るスタイルではないので、気を付けましょう。

// ArraysのObject[]関連ソート用メソッドの定義
public static void sort(Object[] a)
	a - ソートされる配列
public static void sort(Object[] a, int fromIndex, int toIndex)
	a - ソートされる配列
	fromIndex - ソートされる最初の要素(これを含む)のインデックス
	toIndex - ソートされる最後の要素(これを含まない)のインデックス
public static <T> void sort(T[] a, Comparator<? super T> c)
	a - ソートされる配列
	c - 配列の順序を決定するコンパレータ。 null値は、要素の自然順序付けが使用されることを示す。
public static <T> void sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c)
	a - ソートされる配列
	fromIndex - ソートされる最初の要素(これを含む)のインデックス
	toIndex - ソートされる最後の要素(これを含まない)のインデックス
	c - 配列の順序を決定するコンパレータ。 null値は、要素の自然順序付けが使用されることを示す。
String[] strings = { "ABD", "ABB", "ABC" };

Arrays.sort(strings); // 「小さい」順(正順)にソートする
System.out.println(Arrays.toString(strings)); // → ABB、ABC、ABD

Arrays.sort(strings, Collections.reverseOrder()); // 「大きい」順(逆順)にソートする
/* Arrays.sort(strings, Comparator.reverseOrder()); // これでも同じ */
System.out.println(Arrays.toString(strings)); // → ABD、ABC、ABB

開始・終了インデックスの引数があるメソッドは、ソートする範囲を指定できるものです。配列全体ではなく、部分的にソートしたい場合に使えますね。

String[] strings = { "987", "ABD", "ABB", "ABC", "123" };

Arrays.sort(strings, 1, 4);
System.out.println(Arrays.toString(strings)); // → 987、ABB、ABC、ABD、123 (配列のstrings[1..3]がソート範囲)

Arrays.sort(strings, 1, 4, Collections.reverseOrder());
System.out.println(Arrays.toString(strings)); // → 987、ABD、ABC、ABB、123 (同上)

4-2.Collections.sort(List)/reverse(List)でListをソートする

Comparableを格納しているListをソートする際は、Collections.sort(List)/reverse(List)が使えます。逆順にするメソッドがあらかじめ用意されているのが便利ですね。Arraysと同様に引数で与えたList自体の並び順が変わります。

// CollectionsのList関連ソート用メソッドの定義
public static <T extends Comparable<? super T>> void sort(List<T> list)
	list - ソートされるリスト。
public static <T> void sort(List<T> list, Comparator<? super T> c)
	list - ソートされるリスト。
	c - リストの順序を決定するコンパレータ。 null値は、要素の自然順序付けが使用されることを示す。
public static void reverse(List<?> list)
	list - 要素の順序が逆にされるリスト。
List<String> strings = Arrays.asList("ABD", "ABB", "ABC");

Collections.sort(strings); // 「小さい」順(正順)にソートする
System.out.println(strings); // → ABB、ABC、ABD

Collections.reverse(strings); // 「大きい」順(逆順)にソートする
System.out.println(strings); // → ABD、ABC、ABB

4-3.Stream.sorted()でStreamの結果をソートする

Streamの中間操作sorted()を使ってもソートができます。逆順にする場合は、Arraysでも出てきたCollections.reverseOrder()あるいはComparator.reverseOrder()を使います。他の中間操作を行った結果をソートすることも朝飯前なので、色々と柔軟にソートを行えます。

// Streamのソート用メソッドの定義
Stream<T> sorted()
Stream<T> sorted(Comparator<? super T> comparator)
	comparator - ストリーム要素の比較に使用される、非干渉でステートレスなComparator
List<String> strings = Arrays.asList("ABD", "ABB", "ABC");

// 「小さい」順(正順)にソートして、内容を出力してみる
strings.stream().sorted().forEach(System.out::println); // → ABB、ABC、ABD

// 「大きい」順(逆順)にソートして、内容を出力してみる
strings.stream().sorted(Collections.reverseOrder()).forEach(System.out::println); // → ABD、ABC、ABB
/* strings.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println); // これもやっていることは同じ */

4-4.TreeSet/TreeMapからソート済の値/キーを取得する

TreeSetとTreeMapは少し特殊なSetMapで、値・キーを取り出す時は、Comparableでの並び順にしてくれます。TreeSetは値の自動ソート機能が付いたSetTreeSetはキーの自動ソート機能が付いたMapとして覚えておいてもいいでしょう。

Set<String> treeSet = new TreeSet<>();
treeSet.add("ABC");
treeSet.add("ABB");
treeSet.add("ABD");
treeSet.add("ABB"); // 同じ値を入れているが、Setなので格納されるのは1つだけ
treeSet.add("ABC"); // 同上
treeSet.add("ABD"); // 同上

// TreeSetを用いる際は、ソートされていることが保証される
treeSet.forEach(System.out::println); // → ABB、ABC、ABD

Iterator it = treeSet.iterator();
while (it.hasNext()) {
	System.out.println(it.next()); // → ABB、ABC、ABD
}
Map<String, String> treeMap = new TreeMap<>();
treeMap.put("ABC", "あ");
treeMap.put("ABB", "い");
treeMap.put("ABD", "う");

// TreeMapのキーを用いる時は、ソートされていることが保証される
Set<String> keys = treeMap.keySet();
keys.forEach(System.out::println); // → ABB、ABC、ABD

Iterator<String> it = keys.iterator();
while (it.hasNext()) {
	System.out.println(it.next()); // → ABB、ABC、ABD
}

ここで一つ注意事項を。TreeSetTreeMapを使う時は、TreeSetに投入する値・TreeSetで使うキーについて制限があります。比較する2つのインスタンス(e1e2)に対して「e1.equals(e2)trueの場合は、e1.compareTo(e2)0を戻す」を満たさなければなりません。

ですので、Javaの標準APIにあるクラスを使う分にはほとんど問題ありませんが、自作のComparableを使う場合は、制限を満たしているか確認しましょう。標準クラスでの例外は、例えばBigDecimalです。

このように、Object.equalsComparable.compareToの間には、実はちょっとした関係があったりします。これは「自然順序付けがequalsと一貫性がある」とか「compareToで課せられる順序はequalsと一致している」などと言われます。ここでは詳細は延べませんが、興味があれば調べてみると、理解が深まるでしょう。


5.【関連】Comparator.compareの使い方

Comparable.compareToと関係のあるものとして、インターフェイスComparatorのメソッドcompareがあります。

戻り値のintの意味はcompareToと同じで、正負の整数と0による大小比較結果です。ただし、compareToが自分自身と比較先インスタンスを比較していたのに対し、2つの引数同士を比較するのが異なるところです。

// Comparator.compareのメソッド定義
int compare(T o1, T o2)
	o1 - 比較対象の最初のオブジェクト。
	o2 - 比較対象の2番目のオブジェクト。

Comparatorは、ソートしたいクラスからソートのロジック部分を分離するのが主な用途でしょう。ソートを行いたいクラスにComparatorを明示的に実装するのは見かけませんし、意味がありません。使い方も無名クラスやラムダ式で用いられるケースも多いように感じます。

例えば、以下のようにして使います。Comparatorにソートのロジック部分を分離することで、自由にソートのロジックを切り替えられるのです。デフォルトのソートロジックはComparable.compareToで実装して、その他の特殊ケースはComparatorと役割分担することもできます。

// Comparatorを使えば、ソートのロジック部分を自由に切り替えられる
Comparator<User> c1 = new Comparator()<> {
	public int compare(User o1, User o2) {
		return Integer.compare(o1.no, o2.no); // 大小比較のロジック部分は自由に記述する
	}
}

// Comparatorを単純に逆順にするだけなら、Collections.reverseOrder(Comparator)を使うと楽ちん!!
Comparator<User> c2 = Collections.reverseOrder(c1);

List<User> users = ...;
Collections.sort(users, c1); // 番号昇順でのソート
Collections.sort(users, c2); // 番号降順でのソート

6.【参考】Java標準APIのクラスでのcompareToについて

Javaの標準APIにある、良く使われるクラスではどういう基準で大小比較されるのかを簡単にまとめます。これらのクラスは全てComparableを実装しているので、大小比較ができる(=ソートできる)のです。

  • Byte/Short/Integer/Long:保持する整数の大小
  • Float/Double:保持する小数点付き数値の大小
  • BigDecimal/BigInteger:保持する数値の大小
  • Boolean:falsetrueよりも小さいと判断される
  • Character:保持する文字のUnicodeコードポイントの数値の大小
  • String:保持する文字列全体に対して、先頭の文字からCharacterのロジックを用いて大小比較する(辞書順)
  • Date/Calendar/LocalDate/LocalDateTime等:保持する日付・日時がカレンダー的に過去なら小さい、未来なら大きい
  • Enum:定数として宣言された順序値(ordinal()で得られる整数値)の大小で判断

数値のクラスは数字の大小、日付・日時は早い順での判断になります。Booleanは特徴的なので、ぜひ覚えておきましょう。EnumcompareToは使う箇所は少ないかもしれませんね。

文字や文字列は、いわゆる「辞書順」での比較が行われます。直感的にはアルファベット順などの並び順だと思ってもらっても、実用上は構いません。実際には、それぞれの文字に割り当てられているUnicodeコードポイントという数値での比較です。文字・文字列は本質的には数値の集まりだからです。

6-1.Dateはミリ秒までの時間を持っている

DateやCalendarはミリ秒で時間を保持しているので、compareToではミリ秒までが大小比較に反映されます。Dateを日付として扱うなら、compareToする前に時間以下を0でクリアしないと正しく大小比較されません。

以下のような時間以下を0にするメソッドを作っておいてもいいでしょう。ただ、Java 7からのLocalDateTime/ZonedDateTimeなどにはこのような機能が標準でありますし(truncateTo)、日付だけを持つクラスもあるので(LocalDate)、新しいプログラムならそちらを使うのがお勧めです。

// Dateの時間以下を0にするメソッドの例
// caseを追加すれば、月・日にも対応可能
static Date truncate(Date date, int fieldType) {
	Calendar cal = Calendar.getInstance();
	cal.setTime(date);

	switch (fieldType) {
		case Calendar.HOUR_OF_DAY:
			cal.set(Calendar.HOUR_OF_DAY, 0);
		case Calendar.MINUTE:
			cal.set(Calendar.MINUTE, 0);
		case Calendar.SECOND:
			cal.set(Calendar.SECOND, 0);
		case Calendar.MILLISECOND:
			cal.set(Calendar.MILLISECOND, 0);
		default:
			throw new IllegalArgumentException();
	}

	return new Date(cal.getTimeInMillis());
}
// 使用例
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
Date date = new Date();
System.out.println(sdf.format(date)); // → 2018/11/07 12:34:56.789

Date ymd = truncate(date, Calendar.HOUR_OF_DAY);
// Date hour = truncate(date, Calendar.MINUTE);
// Date minute = truncate(date, Calendar.SECOND);
// Date second = truncate(date, Calendar.MILLISECOND);

System.out.println(sdf.format(ymd)); // → 2018/11/07 00:00:00.000

6-2.BigDecimalのcompareToは精度を意識しない

BigDecimalは、保持する数字の表現が複数あります。特に小数点以下の精度が違うケースがあります。でもcompareToの場合は単純に数値としての大小・等しいかどうかが判断されます。equals代わりにcompareToを使おうとすると、結果が違うことがあるので要注意です。

BigDecimal bd1 = new BigDecimal("1.0"); // 精度が小数点以下1桁の1
BigDecimal bd2 = new BigDecimal("1.000"); // 精度が小数点以下3桁の1

System.out.println(bd1.compareTo(bd2)); // → 0なので等しいことになっている
System.out.println(bd1.equals(bd2)); // → false、精度が違うため、違うものとされている

6-3.符号なし整数の大小比較には専用のメソッドがある

Java 8から、整数の符号で使っている1ビットも数値の範囲に入れて計算するための機能追加が行われました(Unsigned Arithmetic Support)。その流れで、大小比較でも正負の符号を意識せずに大小を比較したい場合が出て来ています。

そのような目的のために、Byte/Short/Integer/Longの整数型ラッパークラスへは、compareUnsignedが追加されました。

public static int compareUnsigned(byte x, byte y)
public static int compareUnsigned(short x, short y)
public static int compareUnsigned(int x, int y)
public static int compareUnsigned(long x, long y)
int i1 = Integer.MAX_VALUE;
int i2 = Integer.MAX_VALUE + 1;

System.out.println(Integer.toString(Integer.MAX_VALUE)); // → 2147483647
System.out.println(Integer.toString(i2)); // → -2147483648 (マイナス)
System.out.println(Integer.toUnsigedString(i2)); // → 2147483648 (Integer.MAX_VALUEを超えている!!)

System.out.println(Integer.compare(i1, i2)); // → 1
System.out.println(Integer.compareUnsigned(i1, i2)); // → -1

7.まとめ

この記事では、Comparable.compareToについてお伝えしてきました。compareTo2つのインスタンスの間の大小比較を行い、結果を小さい・等しい・大きいのいずれかで戻すメソッドです。

書いてしまうと単純なものですが、compareToJavaのソート処理の根幹を支えるとても重要なメソッドです。さらに、オブジェクト間の同一性にも関係するメソッドであったりします。縁の下の力持ち的な感じですね。

compareToの基本をしっかりと身に着けて、Javaでのソート処理を自由自在に書けるようになりましょう。

私たちは、全てのエンジニアに市場価値を高め自身の望む理想のキャリアを歩んでいただきたいと考えています。もし、今あなたが転職を検討しているのであればこちらの記事をご一読ください。理想のキャリアを実現するためのヒントが見つかるはずです。

『技術力』と『人間力』を高め市場価値の高いエンジニアを目指しませんか?

『技術力』と『人間力』を高め市場価値の高いエンジニアを目指しませんか?

私たちは「技術力」だけでなく「人間力」の向上をもって遙かに高い水準の成果を出し、関わる全ての人々に感動を与え続ける集団でありたいと考えています。

高い水準で仕事を進めていただくためにも、弊社では次のような環境を用意しています。

  • 定年までIT業界で働くためのスキル(技術力、人間力)が身につく支援
  • 「給与が上がらない」を解消する6ヶ月に1度の明確な人事評価制度
  • 平均残業時間17時間!毎週の稼動確認を徹底しているから実現できる働きやすい環境

現在、株式会社ボールドでは「キャリア採用」のエントリーを受付中です。

まずは以下のボタンより弊社の紹介をご覧いただき、あなたの望むキャリアビジョンをエントリーフォームより詳しくお聞かせください。

コメント

26卒 新卒学生向け主催企業:株式会社ボールド
どんなIT企業なら理想のエンジニアになれるのか?

2時間でIT業界の全てが分かるOne dayインターン

26卒 新卒学生向け主催企業:株式会社ボールド
どんなIT企業なら理想のエンジニアになれるのか?

2時間でIT業界の全てが分かるOne dayインターン