JavaRush /Java Blog /Random-TL /Comparator sa Java

Comparator sa Java

Nai-publish sa grupo
Kamusta! Ngayon ay pag-uusapan natin ang tungkol sa paghahambing ng mga bagay. Hmm... Pero parang napag-usapan na natin ito ng higit sa isang beses? :/ Alam namin kung paano ==gumagana ang “ ” operator, gayundin ang equals()at mga pamamaraan hashCode(). Ang paghahambing ay hindi talaga tungkol doon. Dati, ang ibig naming sabihin ay mas katulad ng "mga bagay sa pagsubok para sa pagkakapantay-pantay." Comparator sa Java - 1Ngunit ang paghahambing ng mga bagay sa bawat isa ay maaaring may ganap na magkakaibang mga layunin! Ang pinaka-halata ay ang pag-uuri. Sa palagay ko kung sasabihin sa iyo na pagbukud-bukurin ang isang listahan ng ArrayList<>mga numero o mga string, maaari mong pangasiwaan ito nang walang mga problema:

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);
   }
}
Output ng console:

[Даша, Маша, Саша]
Mahusay kung naaalala mo ang klase Collectionsat ang pamamaraan nito sort(). Sa palagay ko ay hindi rin magkakaroon ng anumang mga problema sa mga numero. Narito ang isang mas mahirap na gawain para sa iyo:

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);
   }
}
Napakasimple nito: isang klase Carat 3 sa mga bagay nito. Maging napakabait na pag-uri-uriin ang mga kotse sa listahan! Marahil ay itatanong mo: "Paano sila dapat ayusin?" Sa pamamagitan ng pangalan, sa pamamagitan ng taon ng paggawa, sa pinakamataas na bilis? Mahusay na tanong. Hindi namin alam sa ngayon kung paano ayusin ang mga bagay sa klase Car. At, natural, hindi rin ito alam ng Java! Kapag sinubukan naming ipasa Collections.sort()ang isang listahan ng mga bagay sa isang pamamaraan Car, makakatanggap kami ng error:

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);
   }
}
At talaga, paano alam ng wika ang eksaktong paraan kung paano ayusin ang mga bagay na iyong isinusulat? Depende ito sa mga layunin ng iyong programa. Kailangan nating turuan ang Java na ihambing ang mga bagay na ito. At ihambing ang paraan na kailangan natin ito. Para sa layuning ito, ang Java ay may espesyal na tool - interface Comparable. Sa Ingles ito ay isinalin bilang "maihahambing". Upang ang aming mga bagay Caray maihambing sa isa't isa at kahit papaano ay pinagsunod-sunod, dapat ipatupad ng klase ang interface na ito at ipatupad ang tanging paraan nito: 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()

}
Bigyang-pansin:tinukoy namin ang interface Comparable<Car>, hindi lamang Comparable. Ito ay isang na-type na interface, ibig sabihin ay nangangailangan ito ng pagtutukoy ng partikular na klase kung saan ito nauugnay. Sa prinsipyo, <Car>maaari mong alisin ito mula sa interface, ngunit pagkatapos ay inihahambing nito ang mga bagay bilang default Object. Sa halip na isang pamamaraan compareTo(Car o)sa aming klase magkakaroon tayo ng:

@Override
   public int compareTo(Object o) {
       return 0;
   }
Siyempre, mas madali para sa amin na magtrabaho kasama ang Car. Sa loob ng pamamaraan compareTo()ipinatupad namin ang lohika para sa paghahambing ng mga makina. Sabihin nating kailangan nating ayusin ang mga ito ayon sa taon ng paggawa. Marahil ay napansin mo na ang paraan compareTo()ay nagbabalik ng halaga int, hindi boolean. Huwag hayaang mabigla ka nito. Ang katotohanan ay ang paghahambing ng dalawang bagay ay nagbibigay sa amin ng 3 posibleng pagpipilian:
  • а < b
  • a > b
  • a == b.
Mayroon lamang itong boolean2 mga halaga - totoo at mali, na hindi maginhawa para sa paghahambing ng mga bagay. Ang lahat ay intmas simple. Kung ang return value > 0ay , then a > b. Kung ang resulta compareTo < 0ay , kung gayon а < b. Well, kung ang resulta ay == 0, kung gayon ang dalawang bagay ay pantay: a == b. Ang pagtuturo sa aming klase na pagbukud-bukurin ang mga kotse ayon sa taon ng paggawa ay kasingdali ng paghihimay ng mga peras:

@Override
public int compareTo(Car o) {
   return this.getManufactureYear() - o.getManufactureYear();
}
Anong nangyayari dito? Kumuha kami ng isang bagay ng kotse ( this), ang taon ng paggawa ng kotse na ito, at ibawas mula dito ang taon ng paggawa ng isa pang kotse (ang isa kung saan namin inihahambing ang bagay). Kung ang taon ng paggawa ng unang kotse ay mas malaki, ang paraan ay babalik int > 0. Na nangangahulugan na ang isang kotse this >ay isang kotse о. Kung, sa kabaligtaran, ang taon ng paggawa ng pangalawang kotse ( о) ay mas malaki, kung gayon ang pamamaraan ay magbabalik ng negatibong numero, at samakatuwid о > this. Well, kung sila ay pantay, ang pamamaraan ay babalik 0. Ang ganitong simpleng mekanismo ay sapat na upang pagbukud-bukurin ang mga koleksyon ng mga bagay Car! Hindi mo na kailangang gumawa ng iba pa. Narito ka:

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);
   }
}
Output ng console:

[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}]
Ang mga kotse ay inayos ayon sa nararapat! :) Comparator sa Java - 2Sa anong mga kaso dapat itong gamitin Comparable? Ang ipinatupad na paraan ng paghahambing Comparableay tinatawag na "natural na pagkakasunud-sunod". Ito ay dahil sa paraang compareTo()inilalarawan mo ang pinakakaraniwang paraan ng paghahambing na gagamitin para sa mga bagay ng klase na ito sa iyong programa. Ang Natural Ordering ay mayroon na sa Java. Halimbawa, alam ng Java na ang mga string ay kadalasang pinagbubukod-bukod ayon sa alpabeto, at ang mga numero ay kadalasang pinagbubukod-bukod ayon sa pataas na halaga. Samakatuwid, kung tatawagin mo ang pamamaraan sa isang listahan ng mga numero o mga string sort(), pag-uuri-uriin ang mga ito. Kung sa aming programa ang mga kotse ay sa karamihan ng mga kaso ay ihahambing at pinagsunod-sunod ayon sa taon ng paggawa, kung gayon ito ay nagkakahalaga ng pagtukoy ng isang natural na pag-uuri para sa kanila gamit ang interface Comparable<Car>at pamamaraan compareTo(). Ngunit paano kung hindi iyon sapat para sa atin? Isipin natin na ang ating programa ay hindi gaanong simple. Sa karamihan ng mga kaso, ang natural na pag-uuri ng mga kotse (itinakda namin ito ayon sa taon ng paggawa) ay nababagay sa amin. Ngunit kung minsan sa aming mga kliyente ay may mga tagahanga ng mabilis na pagmamaneho. Kung naghahanda kami ng isang katalogo ng mga kotse na mapagpipilian nila, kailangan nilang i-order sa maximum na bilis. Comparator sa Java - 3Halimbawa, kailangan namin ng ganitong pag-uuri sa 15% ng mga kaso. Ito ay malinaw na hindi sapat upang itakda ang natural na pag-uuri ayon Carsa bilis sa halip na taon ng paggawa. Ngunit hindi namin maaaring balewalain ang 15% ng mga kliyente. Anong gagawin natin? Narito ang isa pang interface ay tumulong sa amin - Comparator. Tulad ng , Comparableito ay nai-type. Ano ang pinagkaiba? Comparableginagawang "maihahambing" ang aming mga bagay at lumilikha ng pinaka-natural na pagkakasunud-sunod para sa kanila na gagamitin sa karamihan ng mga kaso. Comparator- ito ay isang hiwalay na klase ng "comparator" (ang pagsasalin ay medyo malamya, ngunit naiintindihan). Kung kailangan nating magpatupad ng ilang partikular na pag-uuri, hindi natin kailangang pumunta sa klase Carat baguhin ang lohika compareTo(). Sa halip, maaari kaming lumikha ng isang hiwalay na klase ng comparator sa aming programa at ituro ito upang gawin ang pag-uuri na kailangan namin!

import java.util.Comparator;

public class MaxSpeedCarComparator implements Comparator<Car> {
  
   @Override
   public int compare(Car o1, Car o2) {
       return o1.getMaxSpeed() - o2.getMaxSpeed();
   }
}
Tulad ng nakikita mo, ang atin Comparatoray medyo simple. Mayroon lamang isang paraan compare()- ito ay isang paraan ng interface Comparator, na dapat ipatupad. Ito ay tumatagal ng dalawang bagay bilang input Carat inihahambing ang kanilang pinakamataas na bilis sa karaniwang paraan (sa pamamagitan ng pagbabawas). Tulad ng compareTo(), ibinabalik nito ang numero int, pareho ang prinsipyo ng paghahambing. Paano natin ito magagamit? Napakasimple:

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 ng console:

[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}]
Gumagawa lang kami ng comparator object at ipapasa ito sa paraan Collections.sort()kasama ang listahang pag-uuri-uriin. Ang pagkakaroon ng nakatanggap ng isang comparator bilang input, ang pamamaraan sort()ay hindi gagamit ng natural na pag-uuri na tinukoy sa paraan compareTo()ng klase Car. Sa halip, ilalapat nito ang algorithm ng pag-uuri mula sa comparator na ipinasa dito. Anong mga pakinabang ang ibinibigay nito sa atin? Una, ang pagiging tugma sa nakasulat na code. Gumawa kami ng bago, partikular na paraan ng pag-uuri, habang pinapanatili ang kasalukuyan, na gagamitin sa karamihan ng mga kaso. Hindi man lang kami gumalaw sa klase Car. Nanatili siya Comparablebilang siya:

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()

}
Pangalawa, flexibility. Maaari tayong magdagdag ng maraming uri hangga't gusto natin. Sabihin, pag-uri-uriin ang mga kotse ayon sa kulay, bilis, timbang, o kung ilang beses ginamit ang kotse sa mga pelikulang Batman. Ito ay sapat lamang upang lumikha ng isang karagdagang isa Comparator. Iyon lang! Ngayon natutunan mo ang dalawang napakahalagang mekanismo na madalas mong gamitin sa mga totoong proyekto sa trabaho. Ngunit, tulad ng alam mo, ang teorya na walang kasanayan ay wala. Samakatuwid, oras na upang pagsamahin ang iyong kaalaman at lutasin ang ilang mga problema! :)
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION