Hai! Hari ini kita akan berbicara tentang membandingkan objek.
Hmm... Tapi bukankah kita sudah membicarakan topik ini lebih dari sekali? :/ Kami tahu cara
Kapan saya harus menggunakan
Misalnya, kita perlu mengurutkan seperti ini 15% dari waktu. Ini jelas tidak cukup bagi kami untuk menetapkan

==
kerja operator, serta metode equals()
dan hashCode()
. Perbandingannya sedikit berbeda. Sebelumnya, kemungkinan besar yang kami maksud adalah "memeriksa objek untuk kesetaraan". Tetapi alasan untuk membandingkan objek satu sama lain bisa sangat berbeda! Yang paling jelas dari ini adalah penyortiran. Saya pikir jika Anda disuruh mengurutkan ArrayList<>
angka atau string, Anda akan dapat menangani ini tanpa masalah:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String[] args) {
String name1 = "Masha";
String name2 = "Sasha";
String name3 = "Dasha";
List<String> names = new ArrayList<>();
names.add(name1);
names.add(name2);
names.add(name3);
Collections.sort(names);
System.out.println(names);
}
}
Keluaran konsol:
[Dasha, Masha, Sasha]
Jika Anda ingat Collections
kelas dan metodenya sort()
, bagus sekali! Saya pikir Anda juga tidak akan kesulitan dengan angka. Inilah tugas yang lebih menantang untuk Anda:
public class Car {
private int manufactureYear;
private String model;
private int maxSpeed;
public Car(int manufactureYear, String model, int maxSpeed) {
this.manufactureYear = manufactureYear;
this.model = model;
this.maxSpeed = maxSpeed;
}
// ...getters, setters, toString()
}
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Car> cars = new ArrayList<>();
Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
Car lambo = new Car(2012, "Lamborghini Gallardo", 290);
Car bugatti = new Car(2010, "Bugatti Veyron", 350);
cars.add(ferrari);
cars.add(bugatti);
cars.add(lambo);
}
}
Tugasnya sebenarnya sederhana. Kami memiliki Car
objek kelas dan 3 Mobil. Apakah Anda berbaik hati mengurutkan mobil dalam daftar? Anda mungkin akan bertanya, "Bagaimana cara memilahnya?" Dengan nama? Menurut tahun pembuatan? Dengan kecepatan maksimum? Pertanyaan yang bagus. Saat ini, kami tidak tahu cara mengurutkan Car
objek. Dan, tentu saja, Java juga tidak mengetahuinya! Saat kami mencoba meneruskan daftar Car
objek ke Collections.sort()
metode, kami mendapatkan kesalahan:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Car> cars = new ArrayList<>();
Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
Car lambo = new Car(20012, "Lamborghini Gallardo", 290);
Car bugatti = new Car(2010, "Bugatti Veyron", 350);
cars.add(ferrari);
cars.add(bugatti);
cars.add(lambo);
// Compilation error!
Collections.sort(cars);
}
}
Dan memang, bagaimana bahasa mengetahui cara mengurutkan objek kelas yang telah Anda tulis? Ini tergantung pada apa yang perlu dilakukan oleh program Anda. Entah bagaimana kita harus mengajarkan Java untuk membandingkan objek-objek ini. Dan untuk membandingkannya seperti yang kita inginkan. Java memang memiliki mekanisme khusus untuk ini: Comparable
antarmuka. Untuk membandingkan dan mengurutkan Car
objek kita, kelas harus mengimplementasikan antarmuka ini, yang terdiri dari satu metode: compareTo()
:
public class Car implements Comparable<Car> {
private int manufactureYear;
private String model;
private int maxSpeed;
public Car(int manufactureYear, String model, int maxSpeed) {
this.manufactureYear = manufactureYear;
this.model = model;
this.maxSpeed = maxSpeed;
}
@Override
public int compareTo(Car o) {
return 0;
}
// ...getters, setters, toString()
}
Tolong dicatatbahwa kami menentukan antarmuka Comparable<Car>
, bukan hanya Comparable
. Ini adalah antarmuka berparameter, yaitu, kita harus menentukan kelas terkait tertentu. Pada prinsipnya, Anda dapat menghapus <Car>
dari antarmuka, tetapi perbandingan akan didasarkan pada Object
objek secara default. Alih-alih compareTo(Car o)
metode, kelas kami akan memiliki:
@Override
public int compareTo(Object o) {
return 0;
}
Tentu saja, jauh lebih mudah bagi kami untuk bekerja dengannya Car
. Di dalam compareTo()
metode, kami menerapkan logika kami untuk membandingkan mobil. Misalkan kita perlu mengurutkannya berdasarkan tahun pembuatan. Anda mungkin memperhatikan bahwa compareTo()
metode mengembalikan an int
, bukan boolean
. Jangan biarkan ini mengejutkan Anda. Saat kita membandingkan dua objek, ada 3 kemungkinan:
а < b
a > b
a == b
.
boolean
hanya memiliki 2 nilai: benar dan salah, yang tidak berfungsi dengan baik untuk membandingkan objek. Dengan int
, semuanya jauh lebih sederhana. Jika nilai kembaliannya adalah > 0
, maka a > b
. Jika hasilnya compareTo
adalah < 0
, maka a < b
. Dan, jika hasilnya == 0
, maka dua objek sama: a == b
. Mengajar kelas kami untuk mengurutkan mobil berdasarkan tahun pembuatannya sangat mudah:
@Override
public int compareTo(Car o) {
return this.getManufactureYear() - o.getManufactureYear();
}
Tapi apa yang terjadi di sini? Kami mengambil satu objek Mobil ( this
), mendapatkan tahun pembuatan mobil ini, dan menguranginya dengan tahun pembuatan mobil lain (yang dibandingkan dengan objek tersebut). Jika tahun pembuatan mobil pertama lebih besar, metode ini akan menghasilkan int > 0
. Artinya this car >
mobil tersebut o
. Sebaliknya, jika tahun pembuatan mobil kedua ( о
) lebih besar, maka metode akan mengembalikan angka negatif, yang berarti o > this
. Terakhir, jika keduanya sama, maka metode akan mengembalikan 0
. Mekanisme sederhana ini sudah cukup bagi kita untuk mengurutkan koleksi Car
objek! Anda tidak perlu melakukan hal lain. Coba lihat:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Car> cars = new ArrayList<>();
Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
Car lambo = new Car(2012, "Lamborghini Gallardo", 290);
Car bugatti = new Car(2010, "Bugatti Veyron", 350);
cars.add(ferrari);
cars.add(bugatti);
cars.add(lambo);
// There was previously an error here
Collections.sort(cars);
System.out.println(cars);
}
}
Keluaran konsol:
[Car{manufactureYear=1990, model='Ferrari 360 Spider', maxSpeed=310},
Car{manufactureYear=2010, model='Bugatti Veyron', maxSpeed=350},
Car{manufactureYear=2012, model='Lamborghini Gallardo', maxSpeed=290}]
Mobil-mobil disortir seperti yang kita inginkan! :) 
Comparable
? Metode pembandingan yang diterapkan di dalam Comparable
disebut pemesanan alami. Ini karena dalam compareTo()
metode Anda menentukan cara yang paling umum, atau alami, untuk membandingkan objek dari kelas ini. Java sudah memiliki tatanan alami. Sebagai contoh, Java tahu bahwa string paling sering diurutkan berdasarkan abjad, dan angka dengan meningkatkan nilai numerik. Oleh karena itu, jika Anda memanggil sort()
metode pada daftar angka atau string, mereka akan diurutkan. Jika program kita biasanya akan membandingkan dan mengurutkan mobil berdasarkan tahun pembuatan, maka kita harus menentukan penyortiran alami untuk Mobil menggunakan antarmuka Comparable<Car>
dancompareTo()
metode. Tetapi bagaimana jika ini tidak cukup bagi kita? Bayangkan program kita tidak sesederhana itu. Dalam kebanyakan kasus, penyortiran mobil secara alami (yang telah kami tetapkan untuk dilakukan berdasarkan tahun pembuatan) cocok untuk kami. Namun terkadang pelanggan kami adalah penggemar berkendara cepat. Jika kita sedang menyiapkan katalog mobil untuk mereka baca dengan teliti, mobil-mobil itu harus diurutkan berdasarkan kecepatan maksimum. 
Car
penyortiran alami kelas berdasarkan kecepatan, bukan berdasarkan tahun pembuatan. Tapi kami tidak bisa mengabaikan 15% pelanggan kami. Jadi apa yang kita lakukan? Antarmuka lain membantu kami di sini: Comparator
. Sama seperti Comparable
, ini adalah antarmuka berparameter. Apa bedanya? Comparable
membuat objek kita "sebanding" dan menentukan urutan pengurutan yang paling alami, yaitu urutan pengurutan yang akan digunakan dalam banyak kasus. Comparator
adalah antarmuka "membandingkan" yang terpisah. Jika kita perlu menerapkan semacam urutan penyortiran khusus, kita tidak perlu masuk ke kelas Car
dan mengubah logika compareTo()
. Sebagai gantinya, kita dapat membuat kelas terpisah yang mengimplementasikan Comparator dan mengajarkannya cara melakukan penyortiran yang kita perlukan!
import java.util.Comparator;
public class MaxSpeedCarComparator implements Comparator<Car> {
@Override
public int compare(Car o1, Car o2) {
return o1.getMaxSpeed() - o2.getMaxSpeed();
}
}
Seperti yang Anda lihat, kami Comparator
cukup sederhana. Kita hanya perlu mengimplementasikan satu metode antarmuka: compare()
. Dibutuhkan dua Car
objek sebagai input dan membandingkan kecepatan maksimumnya dengan cara biasa (dengan pengurangan). Seperti compareTo()
, ia mengembalikan an int
, dan prinsip perbandingannya sama. Bagaimana kita menggunakan ini? Semuanya mudah:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Car> cars = new ArrayList<>();
Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
Car lambo = new Car(2012, "Lamborghini Gallardo", 290);
Car bugatti = new Car(2010, "Bugatti Veyron", 350);
cars.add(ferrari);
cars.add(bugatti);
cars.add(lambo);
Comparator speedComparator = new MaxSpeedCarComparator();
Collections.sort(cars, speedComparator);
System.out.println(cars);
}
}
Keluaran konsol:
[Car{manufactureYear=2012, model='Lamborghini Gallardo', maxSpeed=290},
Car{manufactureYear=1990, model='Ferrari 360 Spider', maxSpeed=310},
Car{manufactureYear=2010, model='Bugatti Veyron', maxSpeed=350}]
Kami cukup membuat objek pembanding dan meneruskannya ke Collections.sort()
metode bersama dengan daftar yang akan diurutkan. Ketika sort()
metode menerima pembanding, itu tidak menggunakan penyortiran alami yang ditentukan dalam metode Car
kelas compareTo()
. Sebagai gantinya, ini menerapkan algoritme pengurutan yang ditentukan oleh pembanding yang diteruskan ke sana. Apa keuntungan melakukan ini? Pertama, kompatibilitas dengan kode yang ada. Kami membuat metode penyortiran khusus yang baru, sembari mempertahankan metode yang sudah ada yang akan sering digunakan. Car
Kami sama sekali tidak menyentuh kelas. Itu adalah Comparable
, dan tetap:
public class Car implements Comparable<Car> {
private int manufactureYear;
private String model;
private int maxSpeed;
public Car(int manufactureYear, String model, int maxSpeed) {
this.manufactureYear = manufactureYear;
this.model = model;
this.maxSpeed = maxSpeed;
}
@Override
public int compareTo(Car o) {
return this.getManufactureYear() - o.getManufactureYear();
}
// ...getters, setters, toString()
}
Kedua, fleksibilitas. Kita dapat menambahkan algoritma pengurutan sebanyak yang kita suka. Misalnya, kita dapat mengurutkan mobil berdasarkan warna, kecepatan, berat, atau berapa kali mobil digunakan dalam film Batman. Yang perlu kita lakukan hanyalah membuat file Comparator
. Itu dia! Hari ini Anda telah mempelajari dua mekanisme yang sangat penting yang akan sering Anda gunakan dalam proyek nyata di tempat kerja. Tapi, seperti yang Anda tahu, teori tanpa praktik bukanlah apa-apa. Sekarang saatnya mengkonsolidasikan pengetahuan Anda dan menyelesaikan beberapa tugas!
GO TO FULL VERSION