JavaRush /Java Blog /Random-ID /Komparator di Jawa

Komparator di Jawa

Dipublikasikan di grup Random-ID
Halo! Hari ini kita akan berbicara tentang membandingkan objek. Hmm... Tapi sepertinya kita sudah membicarakan hal ini lebih dari sekali? :/ Kita mengetahui cara ==kerja operator “ ”, serta metode equals()dan hashCode(). Perbandingan sebenarnya bukan tentang itu. Sebelumnya, yang kami maksud lebih seperti “menguji kesetaraan objek”. Pembanding di Java - 1Namun membandingkan objek satu sama lain mungkin memiliki tujuan yang sangat berbeda! Yang paling jelas adalah penyortiran. Saya pikir jika Anda diminta untuk mengurutkan daftar ArrayList<>angka atau string, Anda dapat mengatasinya 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 = "Даша";

       List<String> names = new ArrayList<>();
       names.add(name1);
       names.add(name2);
       names.add(name3);

       Collections.sort(names);
       System.out.println(names);
   }
}
Keluaran konsol:

[Даша, Маша, Саша]
Sangat bagus jika Anda mengingat kelas Collectionsdan metodenya sort(). Saya rasa tidak akan ada masalah dengan angka juga. Inilah tugas yang lebih sulit 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;
   }

   //...геттеры, сеттеры, 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);
   }
}
Ini sangat sederhana: sebuah kelas Cardan 3 objeknya. Berbaik hatilah untuk mengurutkan mobil-mobil dalam daftar! Anda mungkin akan bertanya: “Bagaimana cara memilahnya?” Berdasarkan nama, berdasarkan tahun pembuatan, berdasarkan kecepatan maksimum? Pertanyaan bagus. Saat ini kami tidak mengetahui cara mengurutkan objek kelas Car. Dan tentu saja, Java juga tidak mengetahui hal ini! Saat kami mencoba meneruskan Collections.sort()daftar objek ke suatu metode Car, kami akan menerima 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);

       //ошибка компилятора!
       Collections.sort(cars);
   }
}
Dan sungguh, bagaimana bahasa tersebut mengetahui secara pasti cara mengurutkan objek yang Anda tulis? Hal ini tergantung pada tujuan program Anda. Kita harus mengajarkan Java untuk membandingkan objek-objek ini. Dan bandingkan bagaimana kita membutuhkannya. Untuk tujuan ini, Java memiliki alat khusus - antarmuka Comparable. Dalam bahasa Inggris ini diterjemahkan sebagai “sebanding”. Agar objek kita Cardapat dibandingkan satu sama lain dan diurutkan, kelas harus mengimplementasikan antarmuka ini dan mengimplementasikan satu-satunya metodenya: 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;
   }

   //...геттеры, сеттеры, toString()

}
Perhatian:kami menentukan antarmuka Comparable<Car>, bukan hanya Comparable. Ini adalah antarmuka yang diketik, artinya memerlukan penentuan kelas tertentu yang terkait dengannya. Pada prinsipnya, <Car>Anda dapat menghapusnya dari antarmuka, tetapi kemudian membandingkan objek secara default Object. Alih-alih metode compareTo(Car o)di kelas kita, kita akan memiliki:
@Override
   public int compareTo(Object o) {
       return 0;
   }
Tentu saja, lebih mudah bagi kami untuk bekerja sama Car. Di dalam metode ini compareTo()kami menerapkan logika untuk membandingkan mesin. Katakanlah kita perlu mengurutkannya berdasarkan tahun pembuatannya. Anda mungkin memperhatikan bahwa metode ini compareTo()mengembalikan nilai int, bukan boolean. Jangan biarkan ini mengejutkan Anda. Faktanya adalah membandingkan dua objek memberi kita 3 kemungkinan pilihan:
  • а < b
  • a > b
  • a == b.
Ia booleanhanya memiliki 2 nilai - benar dan salah, yang tidak nyaman untuk membandingkan objek. Semuanya intjauh lebih sederhana. Jika nilai yang dikembalikan > 0adalah , maka a > b. Jika hasilnya compareTo < 0, maka а < b. Nah, jika hasilnya == 0, maka kedua benda tersebut sama besar : a == b. Mengajari kelas kami untuk menyortir mobil berdasarkan tahun pembuatannya semudah mengupas buah pir:
@Override
public int compareTo(Car o) {
   return this.getManufactureYear() - o.getManufactureYear();
}
Apa yang terjadi di sini? Kita ambil satu objek mobil ( this), tahun pembuatan mobil ini dan kurangi tahun pembuatan mobil lain (yang kita bandingkan objeknya). Jika tahun pembuatan mobil pertama lebih besar, maka metode akan kembali int > 0. Artinya mobil this >tetaplah mobil о. Sebaliknya, jika tahun pembuatan mobil kedua ( о) lebih besar, maka metode tersebut akan menghasilkan angka negatif, dan oleh karena itu о > this. Nah, jika keduanya sama, metodenya akan kembali 0. Mekanisme sederhana seperti itu sudah cukup untuk mengurutkan koleksi objek Car! Anda tidak perlu melakukan hal lain. Ini dia:
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);

       //тут раньше была ошибка
       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 diurutkan sebagaimana mestinya! :) Pembanding di Java - 2Dalam hal apa sebaiknya digunakan Comparable? Metode perbandingan yang diterapkan Comparabledisebut “pengurutan alami”. Hal ini karena dalam metode ini compareTo()Anda menjelaskan metode perbandingan paling umum yang akan digunakan untuk objek kelas ini dalam program Anda. Tatanan Alam sudah hadir di Pulau Jawa. Misalnya, Java mengetahui bahwa string paling sering diurutkan berdasarkan abjad, dan angka paling sering diurutkan berdasarkan nilai menaik. Oleh karena itu, jika Anda memanggil metode pada daftar angka atau string sort(), metode tersebut akan diurutkan. Jika dalam program kami mobil dalam banyak kasus akan dibandingkan dan diurutkan berdasarkan tahun pembuatannya, maka ada baiknya menentukan jenis alami mobil tersebut menggunakan antarmuka Comparable<Car>dan metode compareTo(). Namun bagaimana jika itu tidak cukup bagi kita? Bayangkan program kita tidak sesederhana itu. Dalam kebanyakan kasus, penyortiran mobil secara alami (kami menetapkannya berdasarkan tahun pembuatannya) cocok untuk kami. Namun terkadang di antara klien kami ada penggemar berkendara cepat. Jika kita sedang menyiapkan katalog mobil untuk dipilih, mereka perlu dipesan dengan kecepatan maksimal. Pembanding di Java - 3Misalnya, kita memerlukan penyortiran seperti itu pada 15% kasus. Hal ini jelas tidak cukup untuk menetapkan penyortiran alami berdasarkan Carkecepatan, bukan tahun pembuatan. Tapi kita tidak bisa mengabaikan 15% klien. Apa yang kita lakukan? Di sini antarmuka lain membantu kami - Comparator. Sama seperti , Comparableitu diketik. Apa bedanya? Comparablemembuat objek kita "sebanding" dan membuat urutan paling alami untuk objek tersebut yang akan digunakan dalam banyak kasus. Comparator- ini adalah kelas "pembanding" yang terpisah (terjemahannya sedikit kikuk, tapi bisa dimengerti). Jika kita perlu menerapkan pengurutan tertentu, kita tidak perlu masuk ke kelas Cardan mengubah logikanya compareTo(). Sebagai gantinya, kita dapat membuat kelas pembanding terpisah dalam program kita dan mengajarkannya untuk 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, cara kami Comparatorcukup sederhana. Hanya ada satu metode compare()- ini adalah metode antarmuka Comparator, yang harus diimplementasikan. Dibutuhkan dua objek sebagai masukan Cardan membandingkan kecepatan maksimumnya dengan cara biasa (dengan pengurangan). Seperti compareTo(), ia mengembalikan nomornya int, prinsip perbandingannya sama. Bagaimana kita bisa menggunakan ini? Sangat sederhana:
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}]
Kita cukup membuat objek pembanding dan meneruskannya ke metode Collections.sort()beserta daftar yang akan diurutkan. Setelah menerima pembanding sebagai masukan, metode sort()tidak akan menggunakan pengurutan alami yang ditentukan dalam metode compareTo()kelas Car. Sebaliknya, ia akan menerapkan algoritma pengurutan dari pembanding yang diteruskan ke sana. Keuntungan apa yang diberikan hal ini kepada kita? Pertama, kompatibilitas dengan kode tertulis. Kami menciptakan metode penyortiran baru yang spesifik, sambil mempertahankan metode saat ini, yang akan digunakan dalam banyak kasus. Kami tidak menyentuh kelas sama sekali Car. Dia Comparabletetap apa adanya:
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();
   }

   //...геттеры, сеттеры, toString()

}
Kedua, fleksibilitas. Kita dapat menambahkan sebanyak yang kita inginkan. Misalnya, urutkan mobil berdasarkan warna, kecepatan, berat, atau berapa kali mobil tersebut digunakan dalam film Batman. Cukup membuat yang tambahan saja Comparator. Itu saja! Hari ini Anda 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. Oleh karena itu, inilah saatnya untuk mengkonsolidasikan pengetahuan Anda dan memecahkan beberapa masalah! :)
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION