CodeGym /Java Blog /Acak /Kelas Komparator Java
John Squirrels
Level 41
San Francisco

Kelas Komparator Java

Dipublikasikan di grup Acak
Hai! Hari ini kita akan berbicara tentang membandingkan objek. Kelas Komparator Java - 1 Hmm... Tapi bukankah kita sudah membicarakan topik ini lebih dari sekali? :/ Kami tahu cara ==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 Collectionskelas 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 Carobjek 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 Carobjek. Dan, tentu saja, Java juga tidak mengetahuinya! Saat kami mencoba meneruskan daftar Carobjek 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: Comparableantarmuka. Untuk membandingkan dan mengurutkan Carobjek 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 Objectobjek 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.
booleanhanya 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 compareToadalah < 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 Carobjek! 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! :) Kelas Komparator Java - 2Kapan saya harus menggunakan Comparable? Metode pembandingan yang diterapkan di dalam Comparabledisebut 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. Kelas Komparator Java - 3Misalnya, kita perlu mengurutkan seperti ini 15% dari waktu. Ini jelas tidak cukup bagi kami untuk menetapkan Carpenyortiran 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? Comparablemembuat objek kita "sebanding" dan menentukan urutan pengurutan yang paling alami, yaitu urutan pengurutan yang akan digunakan dalam banyak kasus. Comparatoradalah antarmuka "membandingkan" yang terpisah. Jika kita perlu menerapkan semacam urutan penyortiran khusus, kita tidak perlu masuk ke kelas Cardan 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 Comparatorcukup sederhana. Kita hanya perlu mengimplementasikan satu metode antarmuka: compare(). Dibutuhkan dua Carobjek 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 Carkelas 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. CarKami 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!
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION