JavaRush /Java блогы /Random-KK /Java тіліндегі компаратор

Java тіліндегі компаратор

Топта жарияланған
Сәлеметсіз бе! Бүгін біз an objectілерді салыстыру туралы айтатын боламыз. Хмм... Бірақ біз бұл туралы бірнеше рет айтқан сияқтымыз? :/ Біз « ==» операторының қалай жұмыс істейтінін, сондай-ақ equals()және әдістерін білеміз hashCode(). Салыстыру бұл туралы емес. Бұрын біз «an objectілерді теңдікке сынау» сияқты едік. Java тіліндегі компаратор - 1Бірақ an objectілерді бір-бірімен салыстыру мүлдем басқа мақсаттарға ие болуы мүмкін! Ең айқыны - сұрыптау. Менің ойымша, егер сізге сандар немесе жолдар тізімін сұрыптау керек болса ArrayList<>, оны еш қиындықсыз өңдеуге болады:
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);
   }
}
Консоль шығысы:

[Даша, Маша, Саша]
Егер сіз сыныпты Collectionsжәне оның әдісін еске түсірсеңіз, өте жақсы sort(). Сандармен де проблема болмайды деп ойлаймын. Міне, сізге қиынырақ тапсырма:
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);
   }
}
Бұл өте қарапайым: сынып Carжәне оның 3 нысаны. Тізімдегі көліктерді сұрыптау үшін мейірімді болыңыз! Сіз: «Оларды қалай сұрыптау керек?» Деп сұрайтын шығарсыз. Аты бойынша, шығарылған жылы, максималды жылдамдығы бойынша? Тамаша сұрақ. Қазіргі уақытта сыныптың an objectілерін қалай сұрыптау керектігін білмейміз Car. Және, әрине, Java мұны білмейді! Collections.sort()Нысандар тізімін әдіске беруге тырысқанда Car, біз қатені аламыз:
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);
   }
}
Шынында да, сіз жазған нысандарды қалай сұрыптау керектігін тіл қайдан біледі? Бұл сіздің бағдарламаңыздың мақсаттарына байланысты. Біз Java тілін осы нысандарды салыстыруға үйретуіміз керек. Бізге қажет жолды салыстырыңыз. Осы мақсатта Java-да арнайы құрал бар - интерфейс Comparable. Ағылшын тілінде бұл «салыстырмалы» деп аударылады. CarБіздің нысандарды бір-бірімен салыстыру және қандай да бір түрде сұрыптау үшін сынып осы интерфейсті жүзеге асырып, оның жалғыз әдісін жүзеге асыруы керек: 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()

}
Назар аударыңыз:біз интерфейсті анықтадық Comparable<Car>, жай ғана емес Comparable. Бұл терілген интерфейс, яғни ол байланыстырылған нақты класстың спецификациясын талап етеді. Негізінде <Car>оны интерфейстен жоюға болады, бірақ содан кейін ол нысандарды әдепкі бойынша салыстырады Object. compareTo(Car o)Біздің сыныптағы әдістің орнына бізде болады:
@Override
   public int compareTo(Object o) {
       return 0;
   }
Әрине, бізбен жұмыс істеу оңайырақ Car. Әдістің ішінде compareTo()біз машиналарды салыстыру логикасын жүзеге асырамыз. Оларды шығарылған жылы бойынша сұрыптау керек делік. Сіз байқаған боларсыз, әдіс compareTo()мәнді intемес, қайтарады boolean. Мұның сізді таң қалдыруына жол бермеңіз. Екі нысанды салыстыру бізге 3 ықтимал нұсқаны береді:
  • а < b
  • a > b
  • a == b.
Оның booleanтек 2 мәні бар - шын және жалған, бұл нысандарды салыстыру үшін ыңғайсыз. Барлығы intәлдеқайда қарапайым. Егер қайтарылатын мән > 0болса, онда a > b. Егер нәтиже compareTo < 0болса, онда а < b. Ал, егер нәтиже болса == 0, онда екі нысан тең болады: a == b. Біздің сыныпты автомобильдерді шығарылған жылы бойынша сұрыптауға үйрету алмұрт атқылау сияқты оңай:
@Override
public int compareTo(Car o) {
   return this.getManufactureYear() - o.getManufactureYear();
}
Бұл жерде не болып жатыр? Біз бір автомобиль an objectісін ( this), осы машинаның шығарылған жылын алып, одан басқа машинаның шығарылған жылын алып тастаймыз (an objectіні салыстырамыз). Егер бірінші машинаның шығарылған жылы үлкен болса, әдіс қайтарылады int > 0. Бұл дегеніміз - көлік this >- көлік о. Егер, керісінше, екінші машинаның шығарылған жылы ( о) үлкен болса, онда әдіс теріс санды қайтарады, демек о > this. Егер олар тең болса, әдіс қайтарылады 0. Мұндай қарапайым механизм an objectілер топтамаларын сұрыптау үшін жеткілікті Car! Басқа ештеңе істеудің қажеті жоқ. Міне, ұстаңыз:
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);
   }
}
Консоль шығысы:

[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}]
Вагондар қалай болса солай сұрыпталған! :) Java тіліндегі компаратор - 2Қандай жағдайларда қолдану керек Comparable? Салыстыру әдісі Comparable«табиғи реттілік» деп аталады. Себебі әдісте compareTo()сіз бағдарламаңызда осы класс an objectілері үшін қолданылатын ең көп таралған салыстыру әдісін сипаттайсыз. Табиғи тәртіп Java тілінде бұрыннан бар. Мысалы, Java жолдар көбінесе алфавит бойынша сұрыпталатынын, ал сандар көбінесе өсу мәндері бойынша сұрыпталатынын біледі. Сондықтан, егер сіз әдісті сандар немесе жолдар тізімінде шақырсаңыз sort(), олар сұрыпталады. Comparable<Car>Егер біздің бағдарламамызда автомобильдер көп жағдайда шығарылған жылы бойынша салыстырылып, сұрыпталатын болса, онда интерфейс пен әдісті қолдана отырып, олар үшін табиғи сұрыптауды анықтаған жөн compareTo(). Бірақ бұл бізге жеткіліксіз болса ше? Біздің бағдарламамыз соншалықты қарапайым емес деп елестетіп көрейік. Көп жағдайда автомобильдердің табиғи сұрыпталуы (біз оны шығарылған жылы бойынша белгілейміз) бізге сәйкес келеді. Бірақ кейде біздің клиенттеріміздің арасында жылдам жүргізуді ұнататындар бар. Егер біз олардың таңдауы үшін автокөліктер каталогын дайындайтын болсақ, олар максималды жылдамдықпен тапсырыс беруі керек. Java тіліндегі компаратор - 3Мысалы, мұндай сұрыптау бізге 15% жағдайда қажет. CarБұл шығарылған жылы емес, табиғи сұрыптауды жылдамдық бойынша орнату үшін жеткіліксіз екені анық . Бірақ біз клиенттердің 15%-ын елемеуге болмайды. Біз не істейміз? Мұнда біздің көмекке тағы бір интерфейс келеді - Comparator. Ол сияқты, Comparableтерілген. Айырмашылығы неде? Comparableнысандарымызды «салыстыратын» етеді және олар үшін көп жағдайда қолданылатын ең табиғи сұрыптау тәртібін жасайды. Comparator- бұл жеке «салыстырушы» класы (аударма сәл ыңғайсыз, бірақ түсінікті). Егер қандай да бір нақты сұрыптауды жүзеге асыру қажет болса, бізге сыныпқа кіріп Car, логиканы өзгертудің қажеті жоқ compareTo(). Оның орнына біз өз бағдарламамызда бөлек компаратор класын жасап, оны бізге қажетті сұрыптауды жасауға үйрете аламыз!
import java.util.Comparator;

public class MaxSpeedCarComparator implements Comparator<Car> {

   @Override
   public int compare(Car o1, Car o2) {
       return o1.getMaxSpeed() - o2.getMaxSpeed();
   }
}
Көріп отырғаныңыздай, біздікі Comparatorөте қарапайым. Бір ғана әдіс бар compare()- бұл интерфейс әдісі Comparator, ол жүзеге асырылуы керек. Ол кіріс ретінде екі нысанды қабылдайды Carжәне олардың максималды жылдамдығын әдеттегі әдіспен салыстырады (алу арқылы). сияқты compareTo(), ол санды қайтарады int, салыстыру принципі бірдей. Мұны қалай пайдалана аламыз? Өте оңай:
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);
   }
}
Консоль шығысы:

[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}]
Collections.sort()Біз жай ғана салыстыру нысанын жасаймыз және оны сұрыпталатын тізіммен бірге әдіске береміз . Кіріс ретінде компараторды алғаннан кейін әдіс класс sort()әдісінде анықталған табиғи сұрыптауды пайдаланбайды . Оның орнына ол өзіне берілген компаратордан сұрыптау алгоритмін қолданады. Бұл бізге қандай артықшылықтар береді? Біріншіден, жазылған codeпен үйлесімділік. Біз көп жағдайда қолданылатын қазіргіні сақтай отырып, жаңа, ерекше сұрыптау әдісін жасадық. Біз сыныпқа мүлдем тиіспедік . Ол бұрынғы қалпында қалды: compareTo()CarCarComparable
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()

}
Екіншіден, икемділік. Біз қалағанымызша көптеген сорттарды қоса аламыз. Айталық, көліктерді түсі, жылдамдығы, салмағы немесе Бэтмен фильмдерінде көліктің қанша рет пайдаланылғаны бойынша сұрыптаңыз. Қосымшасын жасау жеткілікті Comparator. Осымен болды! Бүгін сіз жұмыста нақты жобаларда жиі қолданатын екі өте маңызды механизмді білдіңіз. Бірақ, өздеріңіз білетіндей, практикасыз теория ештеңе емес. Сондықтан, біліміңізді бекітіп, бірнеше мәселені шешудің уақыты келді! :)
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION