JavaにおけるComparableとComparatorの違いを徹底解説
はじめに
Javaでは、コレクション(Listなど)の要素を並べ替える際に、ComparableとComparatorという2つのインターフェースを使用できます。どちらもソートのためのインターフェースですが、役割や使い方には明確な違いがあります。
Comparableはjava.langパッケージに属し、「自分自身(this)」と引数で渡された1つのオブジェクトを比較することで、クラス固有の自然順序付けを定義します。一方、Comparatorはjava.utilパッケージに属し、比較対象となる2つのオブジェクトを受け取り、ソートのロジックを外部から柔軟に指定できるのが特徴です。
ComparableとComparatorの比較表
| No. | 項目 | Comparable | Comparator |
|---|---|---|---|
| 1 | メソッド | compareTo(Object a) | compare(Object o1, Object o2) |
| 2 | ソート方法 | Collections.sort(List) を使用 | Collections.sort(List, Comparator) を使用 |
| 3 | ソート順序 | 単一のソート順序(自然順序)のみ定義可能 | 複数のソート順序を定義可能 |
| 4 | 所属パッケージ | java.lang | java.util |
使い分けのポイント
- Comparable:クラス自体に「標準の並び順」を持たせたい場合に実装します。社員番号順や日付順のように、そのクラスにとって最も自然な順序が1つに決まっているケースに向いています。
- Comparator:同じデータでも「名前順」「価格順」「評価順」など、状況に応じて複数の並び替え基準を使い分けたい場合に便利です。対象クラスを修正せずに済むため、既存コードへの影響もありません。
また、Java 8以降ではラムダ式や Comparator.comparing() といったファクトリメソッドを活用することで、Comparatorをより簡潔に記述できます。
Comparableの実装例
以下の例では、LaptopクラスがComparableを実装し、RAM容量を基準とした自然順序付けを定義しています。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ComparableExample {
public static void main(String[] args) {
List<Laptop> laptopList = new ArrayList<>();
laptopList.add(new Laptop("HCL", 16, 800));
laptopList.add(new Laptop("Apple", 8, 100));
laptopList.add(new Laptop("Dell", 4, 600));
Collections.sort(laptopList);
for (Laptop lap : laptopList) {
System.out.println(lap.getRam());
}
}
}
class Laptop implements Comparable<Laptop> {
String name;
int ram;
int price;
public Laptop(String name, int ram, int price) {
this.name = name;
this.ram = ram;
this.price = price;
}
public String getName() {
return name;
}
public int getRam() {
return ram;
}
public void setRam(int ram) {
this.ram = ram;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public int compareTo(Laptop o) {
// RAM容量を昇順で比較
return Integer.compare(this.ram, o.getRam());
}
}
出力結果
4 8 16
RAM容量の小さい順(昇順)に並んでいることが確認できます。
Comparatorの実装例
次の例では、Comparatorを使って名前順にソートしています。比較ロジックをラムダ式として外部から渡せる点が、Comparatorの大きな強みです。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Laptop implements Comparator<Laptop> {
String name;
int ram;
int price;
public Laptop(String name, int ram, int price) {
this.name = name;
this.ram = ram;
this.price = price;
}
public String getName() {
return name;
}
public int getRam() {
return ram;
}
public void setRam(int ram) {
this.ram = ram;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public int compare(Laptop o1, Laptop o2) {
return Integer.compare(o1.getRam(), o2.getRam());
}
public static void main(String[] args) {
List<Laptop> laptopList = new ArrayList<>();
laptopList.add(new Laptop("HCL", 16, 800));
laptopList.add(new Laptop("Apple", 8, 100));
laptopList.add(new Laptop("Dell", 4, 600));
// 名前順でソートするComparator(ラムダ式で記述)
Comparator<Laptop> com =
(Laptop o1, Laptop o2) -> o1.getName().compareTo(o2.getName());
Collections.sort(laptopList, com);
for (Laptop lap : laptopList) {
System.out.println(lap.getName());
}
}
}
出力結果
Apple Dell HCL
名前のアルファベット順にソートされていることがわかります。
まとめ
- Comparable:クラス自身に自然順序を定義するためのインターフェース(compareToメソッドを実装)。
- Comparator:外部から柔軟にソート基準を指定できるインターフェース(compareメソッドを実装)。
- 並び順が1つで十分ならComparable、複数の並び順を使い分けたいならComparatorを選ぶのが基本。
- Java 8以降はラムダ式や
Comparator.comparing()を使うことで、Comparatorをより簡潔に書ける。
-
JavaのIteratorとEnumerationの違いを徹底比較!使い分けのポイントを解説
はじめに:IteratorとEnumerationとはJavaのコレクションフレームワークには、コレクション内の要素を順番に走査(トラバース)しながらアクセスするための仕組みとして「カーソル」が用意されています。その代表格が Iterator(イテレータ) と Enumeration(列挙) の2つです。両者はどちらもコレクションフレームワークに属しますが、登場した時期と役割が異なります。EnumerationはJDK 1.0から存在する歴史あるインターフェースで、IteratorはJDK 1.2でコレクションフレームワークとともに導入された、より新しいインターフェースです。Enumerati
-
JavaでのArrayListとHashSetの違いを徹底解説!使い分けのポイントも紹介
HashSetとArrayListは、どちらもJavaコレクションフレームワークにおいて最も重要なクラスの一つです。それぞれ特徴が異なるため、用途に応じた適切な使い分けが求められます。本記事では、ArrayListとHashSetの主な違いを6つの観点から比較し、実際のサンプルコードとともにわかりやすく解説します。ArrayListとHashSetの違い一覧No.項目ArrayListHashSet1実装インターフェースListインターフェースを実装しています。Setインターフェースを実装しています。2内部構造内部的には配列(動的配列)を使って実装されています。内部的にはHashMapを使って