CodeGym/Blog Java/rawak/Kelas Comparator Java
John Squirrels
Tahap
San Francisco

Kelas Comparator Java

Diterbitkan dalam kumpulan
Hai! Hari ini kita akan bercakap tentang membandingkan objek. Kelas Comparator Java - 1 Hmm... Tetapi bukankah kita sudah membincangkan topik ini lebih daripada sekali? :/ Kami tahu cara ==pengendali berfungsi, serta kaedah equals()dan hashCode(). Perbandingan adalah sedikit berbeza. Sebelum ini, kemungkinan besar kami bermaksud "menyemak objek untuk kesamarataan". Tetapi sebab untuk membandingkan objek antara satu sama lain boleh sama sekali berbeza! Yang paling jelas ialah pengisihan. Saya fikir jika anda diberitahu untuk mengisih ArrayList<>nombor atau rentetan, anda akan dapat menangani ini tanpa sebarang 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);
   }
}
Output konsol:
[Dasha, Masha, Sasha]
Jika anda ingat Collectionskelas dan kaedahnya sort(), syabas! Saya rasa anda juga tidak akan menghadapi masalah dengan nombor. Berikut ialah tugas yang lebih mencabar 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 mudah. Kami mempunyai Carkelas dan 3 objek Kereta. Sudikah anda mengisih kereta dalam senarai? Anda mungkin akan bertanya, "Bagaimanakah ia harus diisih?" Dengan nama? Mengikut tahun pembuatan? Dengan kelajuan maksimum? Soalan yang sangat baik. Pada masa ini, kami tidak tahu bagaimana untuk mengisih Carobjek. Dan, secara semula jadi, Java juga tidak mengetahuinya! Apabila kami cuba menghantar senarai Carobjek kepada Collections.sort()kaedah, kami mendapat ralat:
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 sememangnya, bagaimana bahasa itu tahu cara mengisih objek kelas yang telah anda tulis? Ini bergantung pada apa yang perlu dilakukan oleh program anda. Kita mesti mengajar Java untuk membandingkan objek ini. Dan untuk membandingkannya seperti yang kita mahu. Java mempunyai mekanisme khas untuk ini: Comparableantara muka. Untuk membandingkan dan menyusun Carobjek kita, kelas mesti melaksanakan antara muka ini, yang terdiri daripada satu kaedah: 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()

}
Sila ambil perhatianyang kami tentukan Comparable<Car>antara muka, bukan sahaja Comparable. Ini ialah antara muka berparameter, iaitu, kita mesti menentukan kelas berkaitan khusus. Pada dasarnya, anda boleh mengalih keluar <Car>dari antara muka, tetapi kemudian perbandingan akan berdasarkan Objectobjek secara lalai. Daripada compareTo(Car o)kaedah, kelas kami akan mempunyai:
@Override
   public int compareTo(Object o) {
       return 0;
   }
Sudah tentu, lebih mudah untuk kita bekerja dengan Car. Di dalam compareTo()kaedah, kami melaksanakan logik kami untuk membandingkan kereta. Katakan kita perlu menyusunnya mengikut tahun pembuatan. Anda mungkin perasan bahawa compareTo()kaedah itu mengembalikan int, bukan a boolean. Jangan biarkan ini mengejutkan anda. Apabila kita membandingkan dua objek, terdapat 3 kemungkinan:
  • а < b
  • a > b
  • a == b.
booleanhanya mempunyai 2 nilai: benar dan salah, yang tidak berfungsi dengan baik untuk membandingkan objek. Dengan int, semuanya lebih mudah. Jika nilai pulangan ialah > 0, maka a > b. Jika keputusan compareToialah < 0, maka a < b. Dan, jika hasilnya ialah == 0, maka dua objek adalah sama: a == b. Mengajar kelas kami untuk mengisih kereta mengikut tahun pembuatan adalah mudah:
@Override
public int compareTo(Car o) {
   return this.getManufactureYear() - o.getManufactureYear();
}
Tetapi apa yang berlaku di sini? Kami mengambil satu objek Kereta ( this), dapatkan tahun pembuatan kereta ini, dan tolak daripadanya tahun pembuatan kereta lain (yang dengan objek itu dibandingkan). Jika tahun pembuatan kereta pertama lebih besar, kaedah itu akan mengembalikan int > 0. Ini bermakna kereta this car >itu o. Sebaliknya, jika tahun pembuatan kereta kedua ( о) lebih besar, maka kaedah itu akan mengembalikan nombor negatif, yang bermaksud bahawa o > this. Akhirnya, jika mereka sama, maka kaedah itu akan kembali 0. Mekanisme mudah ini sudah cukup untuk kita mengisih koleksi Carobjek! Anda tidak perlu melakukan apa-apa lagi. Semak ia keluar:
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);
   }
}
Output 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}]
Kereta disusun seperti yang kita mahu! :) Kelas Comparator Java - 2Bilakah saya harus menggunakan Comparable? Kaedah perbandingan yang dilaksanakan dalam Comparabledipanggil susunan semula jadi. Ini kerana dalam compareTo()kaedah anda menentukan cara yang paling biasa, atau semula jadi, untuk membandingkan objek kelas ini. Java sudah mempunyai susunan semula jadi. Sebagai contoh, Java mengetahui bahawa rentetan paling kerap diisih mengikut abjad, dan nombor dengan meningkatkan nilai berangka. Oleh itu, jika anda memanggil sort()kaedah pada senarai nombor atau rentetan, ia akan diisih. Jika program kami biasanya akan membandingkan dan mengisih kereta mengikut tahun pembuatan, maka kami harus menentukan pengisihan semula jadi untuk Kereta menggunakan antara Comparable<Car>muka dancompareTo()kaedah. Tetapi bagaimana jika ini tidak mencukupi untuk kita? Bayangkan program kami tidak begitu mudah. Dalam kebanyakan kes, pengisihan semula jadi kereta (yang kami tetapkan untuk dilakukan mengikut tahun pembuatan) sesuai dengan kami. Tetapi kadangkala pelanggan kami adalah penggemar pemanduan pantas. Jika kita sedang menyediakan katalog kereta untuk mereka teliti, kereta harus disusun mengikut kelajuan maksimum. Kelas Comparator Java - 3Sebagai contoh, katakan kita perlu mengisih seperti ini 15% daripada masa. Ini jelas tidak mencukupi untuk kami menetapkan Carpengisihan semula jadi kelas mengikut kelajuan dan bukannya mengikut tahun pembuatan. Tetapi kami tidak boleh mengabaikan 15% daripada pelanggan kami. Jadi apa yang kita lakukan? Antara muka lain datang untuk membantu kami di sini: Comparator. Sama seperti Comparable, ia adalah antara muka berparameter. Apa perbezaannya? Comparablemenjadikan objek kita "setanding" dan mentakrifkan susunan isihannya yang paling semula jadi, iaitu susunan isihan yang akan digunakan dalam kebanyakan kes. Comparatorialah antara muka "membandingkan" yang berasingan. Jika kita perlu melaksanakan beberapa jenis susunan pengisihan khas, kita tidak perlu masuk ke dalam Carkelas dan menukar logik compareTo(). Sebaliknya, kita boleh mencipta kelas berasingan yang melaksanakan Comparator dan mengajarnya cara melaksanakan pengisihan 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 Comparatoragak mudah. Kita perlu melaksanakan hanya satu kaedah antara muka: compare(). Ia mengambil dua Carobjek sebagai input dan membandingkan kelajuan maksimumnya dengan cara biasa (mengikut penolakan). Seperti compareTo(), ia mengembalikan an int, dan prinsip perbandingan adalah 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);
   }
}
Output 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 hanya mencipta objek pembanding dan menyampaikannya kepada Collections.sort()kaedah bersama-sama dengan senarai untuk diisih. Apabila sort()kaedah menerima pembanding, ia tidak menggunakan pengisihan semula jadi yang ditakrifkan dalam kaedah Carkelas compareTo(). Sebaliknya, ia menggunakan algoritma pengisihan yang ditakrifkan oleh pembanding yang dihantar kepadanya. Apakah kelebihan melakukan ini? Pertama, keserasian dengan kod sedia ada. Kami mencipta kaedah pengisihan khas yang baharu, sambil mengekalkan kaedah sedia ada yang akan digunakan pada kebanyakan masa. Kami tidak menyentuh Carkelas langsung. Ia adalah Comparable, dan ia kekal:
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, fleksibiliti. Kita boleh menambah seberapa banyak algoritma pengisihan yang kita suka. Contohnya, kita boleh mengisih kereta mengikut warna, kelajuan, berat atau berapa kali kereta telah digunakan dalam filem Batman. Apa yang perlu kita lakukan ialah membuat tambahan Comparator. Itu sahaja! Hari ini anda telah mempelajari dua mekanisme yang sangat penting yang sering anda gunakan dalam projek sebenar di tempat kerja. Tetapi, seperti yang anda tahu, teori tanpa amalan bukanlah apa-apa. Kini tiba masanya untuk menyatukan pengetahuan anda dan menyelesaikan beberapa tugas!
Komen
  • Popular
  • Baru
  • Tua
Anda mesti log masuk untuk meninggalkan ulasan
Halaman ini tidak mempunyai sebarang ulasan lagi